ReviseAlgo Logo

Multithreading

Synchronization

Understand thread interference, critical sections, race conditions, and monitor locks.

Interview: Heavily tested on the mechanics of critical sections, how race conditions happen, and the Java monitor lock concept.

Last Updated: June 13, 2026 12 min read

When multiple threads access shared mutable data concurrently, write operations can overlap, causing race conditions. Java uses the synchronized keyword to establish critical sections and enforce mutual exclusion.

Core Idea

A critical section is a block of code accessing shared mutable resources. Mutual exclusion allows only one thread inside at a time.

Why It Matters

Without synchronization, operations like incrementing a variable (counter++) lose updates, leading to invalid data.

Interview Lens

Expect problem-solving questions where you must explain the root cause of a race condition and write code to fix it.

Race Condition and Monitor Locks

A race condition occurs when the outcome of execution depends on the exact interleaving of thread execution paths. For example, count++ is not atomic; it consists of three steps: read, update, and write. Two threads running this concurrently can overlap, resulting in one count update being lost.

Every object in Java is associated with an intrinsic monitor lock (often called a monitor). The synchronized keyword requests the monitor lock of a specified object before executing the associated block or method, ensuring mutual exclusion.

Code Walkthrough

The following example simulates a race condition and demonstrates how synchronization fixes it.

class SynchronizedCounter {
    private int count = 0;

// Mutually exclusive critical section public synchronized void increment() { count++; // Atomic write operation }

public synchronized int getCount() { return count; } }

public class ConcurrencyDemo { public static void main(String[] args) throws InterruptedException { SynchronizedCounter counter = new SynchronizedCounter();

Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } };

Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); t1.join(); t2.join();

System.out.println("Final count (should be 2000): " + counter.getCount()); } }

Interview-Relevant Information

Q: Are intrinsic locks reentrant in Java?
Answer: Yes. Reentrancy means that if a thread already holds a lock on an object, it can acquire the same lock again without blocking. For example, a synchronized method can call another synchronized method on the same object without deadlocking itself.

Quick Checklist

Can you define a race condition? Do you understand what object monitor locks are and how reentrancy works? If yes, you understand basic synchronization.

Use Cases

Protecting shared collections from concurrent modifications in multi-threaded application servers.

Safeguarding state inside singleton utility components.

Common Mistakes

Using different lock objects across threads to protect the same shared state, bypassing mutual exclusion.

Synchronizing read operations unnecessarily when data is immutable, degrading system throughput.