ReentrantLock and ReadWriteLock

Multithreading · lesson 6 of 38 · 4 min read

Use explicit locks when synchronized is too blunt: timeouts, giving up, and concurrent readers.

Open this lesson in the learning hub

Key points

  • ReentrantLock does everything synchronized does, and adds tryLock, timeouts, interruptible waiting and optional fairness.
  • The price is discipline: lock() then try { ... } finally { unlock(); }. Miss the finally and the lock leaks forever.
  • tryLock(timeout) lets a thread give up rather than hang. That is the practical escape hatch from deadlock.
  • ReentrantReadWriteLock lets many readers in at once but writers go alone. Worth it only when reads greatly outnumber writes.
  • StampedLock adds optimistic reads and is faster, but it is not reentrant and is easy to misuse. Reach for it only with numbers in hand.

Example

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main {
    static final ReentrantLock lock = new ReentrantLock();
    static final ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
    static int shared = 0;

    public static void main(String[] args) throws InterruptedException {
        lock.lock();
        try { shared++; } finally { lock.unlock(); }   // unlock ALWAYS goes in finally
        System.out.println("locked update : " + shared);

        Thread hog = new Thread(() -> {
            lock.lock();
            try { sleep(300); } finally { lock.unlock(); }
        });
        hog.start();
        sleep(50);

        boolean got = lock.tryLock(100, TimeUnit.MILLISECONDS);  // give up instead of hanging
        System.out.println("tryLock won   : " + got);
        if (got) lock.unlock();
        hog.join();

        rw.readLock().lock();                          // many readers at once
        try { System.out.println("read value    : " + shared); } finally { rw.readLock().unlock(); }

        rw.writeLock().lock();                         // writers are exclusive
        try { shared = 42; } finally { rw.writeLock().unlock(); }
        System.out.println("after write   : " + shared);
    }

    static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    }
}

synchronized by default. ReentrantLock when you need to time out or walk away.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.