Deep Dive into Java’s synchronized: Object Header, Monitor, and Lock Upgrade Explained
This article explains Java’s synchronized keyword, covering its usage on methods and blocks, the underlying object header and monitor structures, and the lock‑upgrade process from no lock through biased, lightweight, and heavyweight states, illustrated with code samples and diagrams.
Synchronized Overview
Synchronized is a built‑in Java mechanism for thread synchronization. It can be applied to instance methods, static methods, and arbitrary code blocks to guarantee that only one thread executes the protected section at a time.
public class SynchronizedExample {
// synchronized instance method
public synchronized void instanceMethod() {
// thread‑safe code
}
// synchronized static method
public synchronized static void staticMethod() {
// thread‑safe code
}
// synchronized block
public void codeBlock() {
Object lock = new Object();
synchronized (lock) {
// thread‑safe code
}
}
}Object Header
Every Java object in memory starts with an object header that stores runtime metadata. The header consists of three parts:
Mark Word : stores hash code, GC information, lock state, and other flags.
Class Pointer : points to the class metadata, identifying the object's type.
Array Length (optional) : present only for array objects, storing the length.
Typical sizes on a 64‑bit JVM are:
Mark Word – 8 bytes
Class Pointer – 8 bytes
Array Length – 4 or 8 bytes (only for arrays)
Monitor (Synchronization Monitor)
Each object is associated with a monitor that coordinates thread access to synchronized regions. The JVM inserts the bytecode instructions monitorenter and monitorexit at the beginning and end of synchronized methods or blocks.
Acquisition and release follow these steps:
Thread attempts to enter a synchronized method or block and must first obtain the object's monitor.
If the monitor is free, the thread acquires it and proceeds; otherwise it is blocked.
While holding the monitor, the thread executes the critical section.
Contending threads are placed on the monitor’s entry list.
When the thread exits the synchronized region, it releases the monitor, waking waiting threads.
Lock Upgrade Mechanism (JDK 1.6+)
To improve performance, Java introduced a lock‑upgrade strategy that transitions a lock through several states depending on contention.
No Lock : newly created objects have no lock.
Biased Lock : the first thread to acquire the lock biases it toward itself; subsequent entries by the same thread incur virtually no synchronization overhead. The bias is revoked when another thread attempts to acquire the lock.
Lightweight Lock : implemented with CAS (compare‑and‑swap). The thread may spin briefly; if acquisition succeeds, it proceeds. Heavy contention triggers escalation.
Heavyweight Lock : the thread blocks and joins a wait queue; when the lock is released, waiting threads are awakened and compete again.
Understanding these internal mechanisms helps developers write more efficient concurrent code and diagnose performance bottlenecks related to synchronization.
Architect Chen
Sharing over a decade of architecture experience from Baidu, Alibaba, and Tencent.
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.
