JMM semantics for synchronized
When a thread acquires monitor of an object, by entering into a synchronized block of code, it performs a
read barrier (invalidates the local memory and reads from the heap instead). Similarly exiting from a
synchronized block as part of releasing the associated monitor, it performs a write barrier (flushes changes
to the main memory)
Thus modifications to a shared state using synchronized block by one Thread, is guaranteed to be visible to
subsequent synchronized reads by other threads. This guarantee is provided by JMM in presence of
synchronized code block.
JMM semantics for Volatile fields
Read & write to volatile variables have same memory semantics as that of acquiring and releasing a
monitor using synchronized code block. So the visibility of volatile field is guaranteed by the JMM.
Moreover afterwards Java 1.5, volatile reads and writes are not reorderable with any other memory
operations (volatile and non-volatile both). Thus when Thread A writes to a volatile variable V, and
afterwards Thread B reads from variable V, any variable values that were visible to A at the time V was
written are guaranteed now to be visible to B.