Backend Development 8 min read

Using java.util.concurrent.locks.ReentrantLock: Blocking, Interruptible, and Timed Locks in Java

This article explains thread safety in Java multithreading, introduces the ReentrantLock class from java.util.concurrent.locks, demonstrates blocking, interruptible, and timed lock usage with code examples, discusses best practices, fairness, reentrancy, and performance considerations for effective concurrency control.

FunTester
FunTester
FunTester
Using java.util.concurrent.locks.ReentrantLock: Blocking, Interruptible, and Timed Locks in Java

Overview

Thread safety is a core concern in Java multithreaded programming. While the synchronized keyword often suffices for low‑throughput scenarios, more advanced control is provided by the java.util.concurrent package, especially the java.util.concurrent.locks.Lock interface and its implementation java.util.concurrent.locks.ReentrantLock .

Lock Types

Blocking Lock

The method ReentrantLock#lock() acquires the lock and blocks the thread until the lock becomes available.

private static final Logger log = LogManager.getLogger(LockTest.class);
public static void main(String[] args) throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    Thread lockTestThread = new Thread(() -> {
        lock.lock();
        log.info("获取到锁了!");
        lock.unlock();
    });
    lock.lock();
    lockTestThread.start();
    log.info("即将马上释放锁!");
    Thread.sleep(1000);
    lock.unlock();
    lockTestThread.join();
}

Output shows the main thread holds the lock for about one second, during which the child thread blocks until the lock is released.

Interruptible Lock

The method ReentrantLock#lockInterruptibly() also blocks, but throws InterruptedException if the waiting thread is interrupted.

public static void main(String[] args) throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    Thread lockTestThread = new Thread(() -> {
        try {
            lock.lockInterruptibly();
            log.info("获取到锁了!");
            lock.unlock();
        } catch (InterruptedException e) {
            log.warn("获取锁失败!", e);
        }
    });
    lock.lock();
    lockTestThread.start();
    lockTestThread.interrupt();
    lock.unlock();
    lockTestThread.join();
}

The child thread is interrupted before acquiring the lock, resulting in a warning and stack trace.

Timed Lock

Two APIs exist: ReentrantLock#tryLock() (non‑blocking) and ReentrantLock#tryLock(long, TimeUnit) (blocking with timeout). They return a boolean indicating success.

public static void main(String[] args) throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    Thread lockTestThread = new Thread(() -> {
        boolean b = lock.tryLock();
        log.info("第一次获取锁的结果:{}", b);
        try {
            boolean b1 = lock.tryLock(3, TimeUnit.SECONDS);
            log.info("第二次获取锁的结果:{}", b1);
        } catch (InterruptedException e) {
            log.warn("第二次获取锁的时候被中断了");
        }
    });
    lock.lock();
    lockTestThread.start();
    Thread.sleep(1000);
    lock.unlock();
    lockTestThread.join();
}

The first attempt fails because the lock is held; after one second the second attempt succeeds with the timeout.

Best Practices

When using ReentrantLock , wrap lock acquisition in a try‑catch‑finally block to ensure the lock is released:

boolean status = false;
try {
    status = lock.tryLock(3, TimeUnit.SECONDS);
} catch (Exception e) {
    // handle exception
} finally {
    if (status) lock.unlock();
}

Prefer timed locks.

Hold the lock for as short a duration as possible.

Avoid high‑frequency locking.

Reentrancy

ReentrantLock is re‑entrant: the same thread can acquire the lock multiple times, requiring an equal number of unlocks. In most performance tests the re‑entrancy feature is rarely needed, so excessive use is discouraged.

Fair vs. Non‑Fair Locks

The constructor new ReentrantLock(boolean fair) selects a fairness policy. A fair lock grants access in FIFO order, incurring higher context‑switch overhead; a non‑fair lock grants access to the first requesting thread, offering better performance but possible thread starvation.

In most performance‑critical scenarios, non‑fair locks are recommended unless strict ordering is required.

JavaBackend DevelopmentConcurrencylockingThread SafetyReentrantLock
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

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.