There are two important concepts in multithreading environment:
The volatile
keyword eradicates visibility problems, but it does not deal with atomicity. volatile
will prevent the compiler from reordering instructions which involve a write and a subsequent read of a volatile variable; e.g. k++
.
Here, k++
is not a single machine instruction, but three:
So, even if you declare a variable as volatile
, this will not make this operation atomic; this means another thread can see a intermediate result which is a stale or unwanted value for the other thread.
On the other hand, AtomicInteger
, AtomicReference
are based on the Compare and swap instruction. CAS has three operands: a memory location V
on which to operate, the expected old value A
, and the new value B
. CAS
atomically updates V
to the new value B
, but only if the value in V
matches the expected old value A
; otherwise, it does nothing. In either case, it returns the value currently in V
. The compareAndSet()
methods of AtomicInteger
and AtomicReference
take advantage of this functionality, if it is supported by the underlying processor; if it is not, then the JVM implements it via spin lock.