Fundamentals 20 min read

Understanding Java synchronized Keyword, Monitors, and Lock Mechanisms

This article explains the Java synchronized keyword, its three purposes, usage forms for instance methods, static methods, and code blocks, and delves into the underlying monitor mechanism, object header structure, lock states, lock escalation, and related JVM optimizations with illustrative code examples.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding Java synchronized Keyword, Monitors, and Lock Mechanisms

The synchronized keyword is a common tool for thread synchronization in Java concurrency programming. It provides three main functions: mutual exclusion, visibility of shared variable changes, and ordering (although it does not prevent reordering).

Three usage forms of synchronized :

Annotating instance methods

Annotating static methods

Annotating code blocks

1. Annotating Instance Methods

When synchronized precedes an instance method, the lock defaults to the this object.

public class Thread1 implements Runnable {
    // shared resource (critical resource)
    static int i = 0;
    public synchronized void increase() {
        i++;
    }
    public void run() {
        for (int j = 0; j < 10000; j++) {
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread1 t = new Thread1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
        t1.join(); // main thread waits for t1
        t2.join(); // main thread waits for t2
        System.out.println(i);
    }
}

2. Annotating Static Methods

When applied to a static method, the lock is on the Class object.

public class Thread1 {
    static int i = 0;
    public static synchronized void increase() {
        i++;
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int j = 0; j < 10000; j++) {
                increase();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int j = 0; j < 10000; j++) {
                increase();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

3. Annotating Code Blocks

Using synchronized inside a method limits the lock scope to a specific block and can lock on any object.

public class Thread1 implements Runnable {
    static int i = 0;
    @Override
    public void run() {
        for (int j = 0; j < 10000; j++) {
            synchronized (String.class) {
                i++;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread1 t = new Thread1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

Summary of behavior:

For synchronized instance methods, only one thread can enter at a time, acquiring the object's intrinsic lock; other threads block but can still execute other methods.

For synchronized static methods, only one thread can enter, acquiring the class lock.

For synchronized blocks, only one thread can enter the block, acquiring the lock of the specified object or class.

Each class has a class lock, and each object has an intrinsic lock; they are independent, allowing a thread to hold both simultaneously.

Monitor (Lock) Fundamentals

A monitor (also called a synchronization monitor) manages shared variables and the operations on them, ensuring that only one thread can access the protected section at a time.

Object Header Structure

In the JVM heap, each object consists of three parts: padding for alignment, instance fields, and the object header. The header contains two key components:

Klass Pointer : points to the class metadata.

Mark Word : stores runtime data such as hash code, GC age, lock state, and lock pointer.

The lock state is encoded in the Mark Word. Depending on contention, the lock can be in one of four states: no‑lock, biased lock, lightweight lock, or heavyweight lock.

Bytecode Perspective

For synchronized methods, the JVM sets the ACC_SYNCHRONIZED flag. For synchronized blocks, the compiler inserts monitorenter and monitorexit bytecode instructions.

public synchronized void doSth() {
    System.out.println("Hello World");
}

public void doSth1() {
    synchronized (SynchronizedTest.class) {
        System.out.println("Hello World");
    }
}

Decompiling shows the ACC_SYNCHRONIZED flag for the method and explicit monitorenter / monitorexit for the block.

Lock Escalation Process

The JVM upgrades locks based on contention:

Biased Lock : Optimized for the common case where a single thread repeatedly acquires the same lock.

Lightweight Lock : Used when a few threads contend briefly; threads spin on CAS before blocking.

Heavyweight Lock : When contention is high or spinning exceeds a threshold, the lock inflates to a monitor that blocks threads via OS mutexes.

Lock elimination is another JVM optimization where the JIT removes locks that are proven to be uncontended.

Lock Types Comparison

Lock State

Advantages

Disadvantages

Suitable Scenarios

Biased Lock

Near‑zero lock/unlock overhead

Costly when many threads compete

Low contention, same thread repeatedly acquires

Lightweight Lock

Threads spin instead of blocking, fast response

CPU waste if spin lasts too long

Few threads, short lock hold time

Heavyweight Lock

No CPU spin, threads block

Higher latency due to OS context switch

High contention, long lock hold time

In summary, synchronized in Java relies on the monitor (object header) to provide mutual exclusion, visibility, and ordering, with the JVM dynamically adjusting the lock implementation (biased, lightweight, heavyweight) to balance performance and safety.

JavaJVMconcurrencymultithreadingLocksynchronizedMonitor
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.