Java Atomic-are variables really atomic?
As you know, there are a number of Atomic shells for primitives. The main principle is that they do not use the usual synchronization (synchronized), but implement "Compare and Set operation".
For example, take AtomicLong. To increase the current value, there is a method getAndAdd.
Let's take a look at sortsy:
private volatile long value;
public final long get() {
return value;
}
public final long getAndAdd(long delta) {
while (true) {
long current = get();
long next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
Question: where is the atomicity of the operation here? What prevents another thread from going inside while, or even changing the value of value, to pass to next is not at all something to be filtered in current?
Especially since value is declared as volatile, which means that this value is common to all potential threads.
1 answers
Что мешает другому потоку зайти внутрь while или вообще, поменяв значение value, передать в next совсем не то, чтобы просечено в current?
You don't understand how competing threads work. The fact that other threads can enter the while
loop is not a big deal. The variables current
and next
are local, and therefore each thread has its own instances of these variables.
The problem is only in the shared state, i.e. the variable value
. Since the variable value
is declared with the modifier volatile
, it is guaranteed that the relation happens-before, which leads to the fact that the changed value of this variable will be seen by everyone streams.
The compareAndSet
method is an optimistic locking mechanism and allows you to change the value of value
only if it is equal to the expected value (i.e. current
).
If the value of value
was changed in another thread, it will not be equal to the expected value. Therefore, the compareAndSet
method will return the value false
, which will result in a new iteration of the while
loop in the getAndAdd
method. I.e., a new value value
will be reassigned to the current
variable, after which it will be produced addition and a new attempt to write the resulting value (i.e. next
).