Unlocking Java Concurrency: How volatile and synchronized Really Work
This article explains the low‑level workings of Java's volatile keyword and synchronized construct, detailing how they ensure memory visibility and exclusive access, and describes the JVM's lock optimizations such as biased, lightweight, heavyweight, and spin locks.
Background
For Java, source code is compiled to bytecode, loaded by the class loader into the JVM, and executed as machine instructions; the concurrency mechanism relies on the JVM implementation and CPU instructions.
volatile implementation principle
volatile has two main effects: it prevents instruction reordering and provides memory visibility for shared variables across threads. When a thread writes to a volatile variable, the JVM forces the cache line to be flushed to main memory and invalidates the cached copies in other CPUs, guaranteeing that other threads can read the updated value. This lightweight synchronization is cheaper than synchronized because it avoids thread context switches.
Implementation details: the JVM issues a lock‑prefix instruction to write back the cache line, and the hardware cache‑coherence protocol ensures other processors see the change.
synchronized implementation principle
synchronized can annotate methods or be used as a synchronized block, ensuring that only one thread can execute the protected code at a time while providing visibility and exclusivity.
Example code (see image). After compiling, running javap.exe -v Synchronized.class shows the generated bytecode.
The bytecode reveals that a synchronized block is implemented with the monitorenter and monitorexit instructions, while a synchronized method carries the ACC_SYNCHRONIZED flag.
Both mechanisms acquire the object's monitor; a thread must obtain this monitor before entering the block or method, otherwise it is blocked (state BLOCKED).
The monitor is an intrinsic lock associated with every object; threads compete for it via a wait queue.
JVM optimizations for synchronized
Because synchronized is relatively heavy, since JDK 1.6 the JVM introduces several lock optimizations: biased lock, lightweight lock, heavyweight lock, and spin lock. The object header (Mark Word) stores lock state; a lock can be in one of four states—no lock, biased, lightweight, heavyweight—and can be upgraded but not downgraded.
Biased lock
The core idea of biased locking is that if a thread repeatedly acquires a lock, the lock becomes biased toward that thread, allowing subsequent acquisitions without any synchronization instructions.
Acquisition flow: when a thread enters a synchronized block, the JVM stores the thread ID in the object header and stack frame. Later entries simply check the Mark Word; if it still points to the same thread, no CAS operation is needed. If contention occurs, the lock upgrades to a lightweight lock.
Lightweight lock
If biased locking fails, the JVM uses a lightweight lock, which stores a pointer in the object header to the owning thread’s stack frame. Successful acquisition lets the thread enter the critical section; failure causes the lock to inflate to a heavyweight lock.
Spin lock
When a lightweight lock inflates to a heavyweight lock, the JVM may first spin—perform a few empty loops—before putting the thread to sleep, attempting to acquire the lock without a costly OS context switch. Spin locks cannot be downgraded once the lock becomes heavyweight.
Comparison of three locks
Other JVM lock optimizations
Beyond the above, the JVM also performs lock elimination, uses CAS operations, and employs lock‑free techniques to further reduce synchronization overhead.
References
1. http://blog.csdn.net/wolegequdidiao/article/details/45116141
2. http://ifeve.com/volatile/
3. http://www.jianshu.com/p/425b44267afe
4. Portions of the content are from "Java Concurrency in Practice".
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
