An Introduction to Java synchronized: Features, Implementation, and Optimizations
This article explains the Java synchronized keyword, detailing its four core properties—atomicity, visibility, ordering, and reentrancy—while illustrating its bytecode behavior, lock types, upgrade mechanisms, and JVM optimizations such as biased, lightweight, and heavyweight locks, lock elimination, and lock coarsening.
Overview of synchronized
The synchronized keyword in Java ensures that at most one thread can execute a block of code at a time, providing thread‑safety by acting as a lock on objects, methods, or code blocks.
Four Core Properties
Atomicity : Operations protected by synchronized execute without interruption, preventing race conditions. Basic reads/writes of primitive types are atomic, while compound operations like a++ are not.
Visibility : When a lock is released, changes in a thread’s working memory are flushed to main memory, making them visible to other threads.
Ordering : Only one thread can hold the lock at a time, guaranteeing a deterministic execution order.
Reentrancy : A thread that already holds a lock can reacquire it, allowing nested synchronized blocks.
Bytecode Illustration
Compiling a simple synchronized block produces the following bytecode instructions:
public class TestSynchronized implements Runnable {
@Override
public void run() {
synchronized (this) {
System.out.println("同步代码块");
}
}
public static void main(String[] args) {
TestSynchronized sync = new TestSynchronized();
Thread t = new Thread(sync);
t.start();
}
}The compiled bytecode contains a monitorenter before the block and a monitorexit after it. Two monitorexit instructions may appear to ensure the lock is released even if an exception occurs.
Lock Types and Upgrade Path
JVM lock implementations have evolved:
Biased Lock : The thread ID is stored in the object’s mark word when there is no contention.
Lightweight (Thin) Lock : Used under low contention; threads spin and use CAS on the mark word.
Heavyweight (Fat) Lock : Falls back to OS mutex when contention is high, avoiding excessive CPU spinning.
Lock Elimination : The JIT removes locks that are proven to be uncontended.
Lock Coarsening : The JIT expands the lock scope to reduce repeated lock/unlock overhead.
Lock state is stored in the object header’s markword. By inspecting the mark word with tools like JOL (Java Object Layout), developers can see the transition from no‑lock (001) to biased (101), lightweight (00), and heavyweight (10) states.
Practical Code for Object Layout Inspection
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
public class JaveObjectLayout {
public static void main(String[] args) {
Object o = new Object();
String s = ClassLayout.parseInstance(o).toPrintable();
System.out.println(s);
}
}Running this program prints the object's mark word, showing lock information before and after synchronization.
Summary
The synchronized keyword provides a simple yet powerful mechanism for achieving thread safety in Java. Understanding its underlying lock states, bytecode behavior, and JVM optimizations helps developers write more efficient concurrent code and answer common interview questions about Java concurrency.
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.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
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.
