Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Concurrency & Multithreading

Threads & Runnable

  • Introduction to Threads
  • ExecutorService & Thread Pools

Synchronization & Memory Model

  • synchronized and Locks
  • volatile and the Memory Model
  • CompletableFuture

Concurrent Collections

  • ConcurrentHashMap & CopyOnWriteArrayList
Chaturmind
← Java Concurrency & Multithreading

Threads & Runnable

  • Introduction to Threads
  • ExecutorService & Thread Pools

Synchronization & Memory Model

  • synchronized and Locks
  • volatile and the Memory Model
  • CompletableFuture

Concurrent Collections

  • ConcurrentHashMap & CopyOnWriteArrayList
HomeLearnJavaJava ConcurrencySynchronization
✓ FreeAdvanced· 14 min read

Synchronized and Locks

Use synchronized blocks, ReentrantLock, ReadWriteLock, and StampedLock to protect shared state.

Published February 12, 2025


Synchronized and Locks in Java

When multiple threads access shared mutable state, you need mutual exclusion — only one thread should modify the state at a time. Java offers two mechanisms: the synchronized keyword and the java.util.concurrent.locks package.

synchronized — the basics

public class Counter {
    private int count = 0;

    // Method-level lock (locks on 'this')
    public synchronized void increment() {
        count++;
    }

    // Block-level lock (preferred — smaller critical section)
    public void incrementBlock() {
        synchronized (this) {
            count++;
        }
    }

    // Static synchronized — locks on the Class object
    public static synchronized void staticMethod() { ... }
}

Intrinsic Locks (Monitors)

Every Java object has an intrinsic lock (monitor). synchronized acquires this lock on entry and releases it on exit — even if an exception is thrown.

// Two synchronized methods on the same object share the same lock
public class BankAccount {
    private double balance;

    public synchronized void deposit(double amount)  { balance += amount; }
    public synchronized void withdraw(double amount) { balance -= amount; }
    // deposit and withdraw cannot run concurrently on the same BankAccount
}

ReentrantLock — explicit locking

import java.util.concurrent.locks.*;

public class Counter {
    private final ReentrantLock lock = new ReentrantLock();
    private int count = 0;

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock(); // ALWAYS unlock in finally!
        }
    }

    // Try to acquire lock without blocking
    public boolean tryIncrement() {
        if (lock.tryLock()) {
            try { count++; return true; }
            finally { lock.unlock(); }
        }
        return false;
    }

    // Try with timeout
    public boolean tryIncrementTimeout() throws InterruptedException {
        if (lock.tryLock(100, TimeUnit.MILLISECONDS)) {
            try { count++; return true; }
            finally { lock.unlock(); }
        }
        return false;
    }
}

ReentrantReadWriteLock — multiple readers, exclusive writers

public class Cache<K, V> {
    private final Map<K, V> map = new HashMap<>();
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock  = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();

    public V get(K key) {
        readLock.lock();       // multiple threads can read simultaneously
        try { return map.get(key); }
        finally { readLock.unlock(); }
    }

    public void put(K key, V value) {
        writeLock.lock();      // exclusive write access
        try { map.put(key, value); }
        finally { writeLock.unlock(); }
    }
}

Condition Variables

public class BoundedQueue<T> {
    private final Queue<T> queue = new LinkedList<>();
    private final int capacity;
    private final Lock lock = new ReentrantLock();
    private final Condition notFull  = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public void put(T item) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == capacity) notFull.await();
            queue.add(item);
            notEmpty.signal();
        } finally { lock.unlock(); }
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) notEmpty.await();
            T item = queue.poll();
            notFull.signal();
            return item;
        } finally { lock.unlock(); }
    }
}

synchronized vs ReentrantLock

FeaturesynchronizedReentrantLock
Auto-unlock on exception✅❌ (need finally)
Fairness policyNoYes (new ReentrantLock(true))
tryLock()No✅
Multiple conditionsNo✅
Code readabilityBetterMore verbose

Interview Tips

  1. Deadlock: Thread A holds lock 1, wants lock 2; Thread B holds lock 2, wants lock 1. Prevention: always acquire locks in the same order.
  2. synchronized is reentrant — a thread holding the lock can re-enter synchronized methods on the same object without blocking.
  3. volatile is NOT a replacement for synchronized — it only guarantees visibility, not atomicity of compound operations.

Previous

ExecutorService & Thread Pools

Next

volatile and the Memory Model

AI Tutor

Lesson: Synchronized and Locks

Quick actions

AI responses can be inaccurate. Verify critical information.