Understanding synchronized in Java: Mechanism and Modern Implementation

1. Overview of synchronized

The synchronized keyword in Java is a built-in mechanism to ensure synchronization across threads when accessing shared resources.

2. Internal Implementation of synchronized

Java Virtual Machine (JVM) implements synchronization using monitors (Monitor objects).

2.1 Method-Level Synchronization

From JDK 9+, performance improvements have been introduced in handling monitor acquisition for synchronized methods, especially after a biased or lightweight locking attempt fails.

2.2 Block-Level Synchronization

3. What Really Happens When You Use synchronized

3.1 Mark Word in Object Header

Biased Locking is disabled by default starting in JDK 15 and has been completely removed in JDK 21. The JVM now favors lightweight or heavyweight locks, improving predictability in multi-threaded environments.

3.2 ObjectMonitor in HotSpot JVM

The internal structure and scheduling logic of ObjectMonitor have been optimized, including better support for lock elimination, fast-path locking, and improved interaction with LockSupport’s park/unpark.

4. Lock Optimization Techniques

Java supports multiple lock states to optimize synchronization performance.

Lock Type Description
No Lock Default state when the object is not locked by any thread.
Lightweight Lock Utilizes CAS (Compare-And-Swap) to acquire the lock in user space; efficient in low-contention scenarios.
Biased Lock Deprecated: Previously used for non-contending threads, but removed in JDK 21.
Heavyweight Lock Used under high contention; threads are blocked in OS kernel, involving context switches.

5. Best Practices