Atomic Variables
In Java, Atomic variables refer to the variables which can be only accessed by one thread at a time. This is achieved using the CPU's cache line serialization method described here.
CPU provides this feature of serializing access to a memory address via a special instruction. Java simply uses it to achieve this.
CAS - Compare and Saveβ
Compare and Save is just one of the features of atomic variables.
Since atomic variables only ensure atomicity just for that specific line and given that this is handled at CPU level, it can happen that even before the next line runs, another thread has acquired the lock and updated the value.
Synchronizedβ
This is used to achieve atomicity of functions or code blocks but doesn't use CPU features.
JVM sets the metadata of the object on which the synchronized block is defined. When a thread enters the synchronized block, it acquires the lock on the object. No other thread can enter any synchronized block on the same object until the lock is released.
Waiting thread can either fully JVM handled or can be handled by OS.
- Spin-wait - keep checking in a loop until the lock is released.
- Fat Lock - If it's taking long, JVM will decide to use OS. OS will put the thread to sleep and wake it up when the lock is released.
The entire synchronized implementation is built on top of CPU's atomicity feature. When thread tires to acquire the lock, it uses the CPU's atomic instruction to set the metadata of the object. This ensures that only one thread can set the metadata at a time.