我尝试为2个AtomicReferences实现交换方法。
public void swap(AtomicReference<Object> a, AtomicReference<Object> b) {
while (true) {
Object value1 = a.get();
Object value2 = b.get();
if (a.compareAndSet(value1, value2) && b.compareAndSet(value2, value1)) return;
}
}
我认为这种解决方案是不正确的。如果多个线程同时使用此方法,则可能导致以下情况:
T1: ...get(); get(); compareAndSet() == true //-> BREAK (scheduler)
T2: ...get(); get(); compareAndSet() == true; compareAndSet() == true; return;
这意味着,T1已经设置了
a
的值,但是将通过设置b的值而失败。如果已设置AtomicReference a,则T1将重复该过程,甚至。你们中有人是否有更好的主意,如何实现这样的目标?如果您只有一个AtomicReference,那将很容易。也许不可能使用2个AtomicReference,我应该考虑使用一个指向Object []的AtomicReference。
在Scala中,此方法超级容易实现,因为您有原子块。
class Swappy[A](_a: A, _b: A) {
@volatile
var a = Ref(_a)
@volatile
var b = Ref(_b)
def swap(): Unit = {
atomic {
implicit tx =>
val tmp = a
a = b
b = tmp
}
}
def elems: (A, A) = (a.single(), b.single())
}
最佳答案
我用另一种方法创建了一个解决方案。这应该是100%线程安全的。我改用了一个AtomicReference。如果有人能找到更好的方法,请随时写一个答案。 :)
package test;
import java.util.concurrent.atomic.*;
public class ScalaSTMPendant {
AtomicReference<Object[]> a;
public ScalaSTMPendant(Object a, Object b) {
this.a = new AtomicReference<>(new Object[] {a,b});
}
public void swap() {
while (true) {
Object[] origin = a.get();
Object[] swapped = new Object[] {origin[1], origin[0]};
if (a.compareAndSet(origin, swapped)) return;
}
}
public Object[] elems() {
Object[] temp = a.get();
return new Object[] {temp[0], temp[1]};
}
}