Synchronized Block in Java

Naveen AnamaneniUpdated · 4 min read

A synchronized block in Java locks only part of a method: the lines inside the block. You choose which object's lock to use by writing it in parentheses: synchronized (lock) { ... }. Compared with a synchronized method, a block holds the lock for less time, so other threads wait less, and it lets you use a private lock object that outside code can't interfere with. In this lesson, you will learn the syntax, how to choose a lock, and when to prefer blocks over methods.

Syntax

Syntax
synchronized (lockObject) {
    // only one thread at a time, per lockObject
}
Lock written asLocks
synchronized (this)The current object, like a synchronized method
synchronized (lock)A private object kept just for locking
synchronized (Account.class)The class, like a static synchronized method

Example: Locking Only What Needs It

Let's see an example where slow work happens outside the lock and only the shared update is synchronized.

BlockDemo.java▶ Try it
import java.util.ArrayList;
import java.util.List;
 
public class BlockDemo {
    private final List<String> results = new ArrayList<>();
    private final Object lock = new Object();
 
    void process(String name) {
        String report = slowFormat(name);
        synchronized (lock) {
            results.add(report);
        }
    }
 
    static String slowFormat(String name) {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return name.toUpperCase();
    }
 
    public static void main(String[] args) throws InterruptedException {
        BlockDemo demo = new BlockDemo();
        long start = System.nanoTime();
        List<Thread> threads = new ArrayList<>();
        for (String n : List.of("Navika", "Srihitha", "Advitha", "Anamaneni")) {
            Thread t = new Thread(() -> demo.process(n));
            threads.add(t);
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }
        long ms = (System.nanoTime() - start) / 1_000_000;
        synchronized (demo.lock) {
            System.out.println("Reports collected: " + demo.results.size());
        }
        System.out.println("Ran in parallel (under 600 ms)? " + (ms < 600));
    }
}
Output
Reports collected: 4
Ran in parallel (under 600 ms)? true

Explanation: The slow formatting (200 milliseconds) happens outside the lock, so all four threads do it at the same time. Only results.add is inside synchronized (lock), which takes a moment. If the whole process method were synchronized, the four slow steps would run one after another, taking 800 milliseconds.

Why Use a Private Lock Object?

With synchronized (this) or synchronized methods, the lock is the object itself, which any code holding a reference can also lock, accidentally or on purpose, blocking your methods. A private final Object lock = new Object(); can only be used by your class, so no outside code can interfere.

Synchronized Method vs Block

Synchronized methodSynchronized block
Lock held forThe whole methodOnly the block
Lock objectthis or the classAny object you choose
Private lock possibleNoYes
Typical useSmall methods that touch shared data throughoutMethods with slow parts that don't need the lock

Common Mistakes

Locking on a field that is later reassigned. Threads then lock different objects; make the lock final.

Leaving a read of the shared data outside the block. Reads need the lock too.

Synchronizing on "lock" or Integer.valueOf(1). These objects are shared across the JVM.

Interview Corner

What is the difference between a synchronized method and a synchronized block?

A synchronized method acquires the lock of this (or of the class object for static methods) for the entire method body. A synchronized block acquires the lock of an explicitly specified object only for the statements inside the block. Blocks reduce the time the lock is held, allow finer-grained locking, and let you use a private lock object that external code can't acquire.

Practice

  1. Easy: Rewrite a fully synchronized Counter.increment() method using a private lock object and a synchronized block.
  2. Harder: Write a class with two independent counters, each guarded by its own lock object, so increments of different counters never wait for each other.

Quick check: Synchronized block

4 questions
1Which lock does synchronized (lock) { } use?
2Why move slow work outside the synchronized block?
3Why prefer a private final lock object?
4Which is a bad lock object?

Key Takeaways

Was this tutorial helpful?

Lesson 399 of 482