Java exposes the CAS operation through its atomic classes, e.g.
boolean compareAndSet(expected,update)
The JavaDocs specifies the memory effects of a compareAndSet operation as follows:
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
This definitely holds for successful compareAndSet
invocations. But do the memory effects also hold if compareAndSet returns false
?
I would say that an unsuccessful compareAndSet
corresponds to a volatile read (as the current value of the atomic instance has to be accessed in this case), but I do not see why an CAS should perform special memory barrier instructions in the unsuccessful case.
The question actually is, whether an unsuccessful CAS also establishes a happens-before relationship. Consider the following program:
public class Atomics {
private static AtomicInteger ai = new AtomicInteger(5);
private static int x = 0;
public static void main(String[] args) {
new Thread(() -> {
while (x == 0) {
ai.compareAndSet(0, 0); // returns false
}
}, "T1").start();
new Thread(() -> {
x = 1;
ai.compareAndSet(0, 0); // returns false
}, "T2").start();
}
}
Will thread T2 (and the program) definitely terminate?