Mastering Java ReentrantLock: Blocking, Interruptible, and Timeout Locks Explained
This article explains the Java java.util.concurrent.locks.Lock interface and its ReentrantLock implementation, detailing the advantages of reentrancy, interruptibility, and timeout features, and provides practical code examples for blocking, interruptible, and timed lock acquisition along with best‑practice recommendations.
Lock Overview
If you have encountered thread‑safety issues, you are likely familiar with the concept of a lock. In Java, the java.util.concurrent.locks.Lock interface defines the contract for lock implementations, and the most commonly used implementation in performance testing is java.util.concurrent.locks.ReentrantLock. Compared with the synchronized keyword, ReentrantLock offers reentrancy, greater flexibility, interruptibility, and higher performance through fair and non‑fair lock modes.
Blocking Lock
The blocking lock is obtained via ReentrantLock#lock(), which has no parameters and blocks the calling thread until the lock is acquired.
package org.funtester.performance.books.chapter02.section3;
import java.util.concurrent.locks.ReentrantLock;
/**
* Blocking lock example
*/
public class BlockingLockDemo {
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock(); // create a reentrant lock
Thread lockTestThread = new Thread(() -> {
System.out.println(System.currentTimeMillis() + " Async thread started! " + Thread.currentThread().getName());
lock.lock(); // acquire lock
System.out.println(System.currentTimeMillis() + " Got the lock! " + Thread.currentThread().getName());
lock.unlock(); // release lock
});
lock.lock(); // main thread acquires lock first
lockTestThread.start(); // start async thread
Thread.sleep(100); // sleep 100 ms
System.out.println(System.currentTimeMillis() + " About to release lock! " + Thread.currentThread().getName());
lock.unlock(); // release lock
}
}The async thread starts, sleeps for 100 ms while the main thread holds the lock, then acquires the lock and prints its log after the main thread releases it. This behavior mirrors that of synchronized in many performance‑testing scenarios.
Interruptible Lock
The interruptible lock is obtained via ReentrantLock#lockInterruptibly(). It blocks like the regular lock, but if the waiting thread is interrupted, it throws java.lang.InterruptedException.
package org.funtester.performance.books.chapter02.section3;
import java.util.concurrent.locks.ReentrantLock;
/**
* Interruptible lock example
*/
public class InterruptiblyLockDemo {
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock(); // create a reentrant lock
Thread lockTestThread = new Thread(() -> {
try {
lock.lockInterruptibly(); // acquire lock interruptibly
System.out.println(System.currentTimeMillis() + " Got the lock! " + Thread.currentThread().getName());
lock.unlock(); // release lock
} catch (InterruptedException e) {
System.out.println(System.currentTimeMillis() + " Thread was interrupted! " + Thread.currentThread().getName());
}
});
lock.lock(); // main thread acquires lock first
lockTestThread.start(); // start async thread
lockTestThread.interrupt(); // interrupt async thread
lock.unlock(); // release lock
}
}In this example the async thread is interrupted before it can acquire the lock, causing the exception to be caught and a single line of output indicating the interruption.
Timeout Lock
Two timeout‑acquisition methods are available: ReentrantLock#tryLock() (immediate attempt) and ReentrantLock#tryLock(long, TimeUnit) (wait up to the specified timeout). Both return a boolean indicating success.
package org.funtester.performance.books.chapter02.section3;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* Timeout lock example
*/
public class TimeoutLockDemo {
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock(); // create a reentrant lock
Thread lockTestThread = new Thread(() -> {
boolean b = lock.tryLock(); // first immediate attempt
System.out.println(System.currentTimeMillis() + " First try result: " + b + " " + Thread.currentThread().getName());
try {
boolean b1 = lock.tryLock(3, TimeUnit.SECONDS);
System.out.println(System.currentTimeMillis() + " Second try result: " + b1 + " " + Thread.currentThread().getName());
} catch (InterruptedException e) {
System.out.println(System.currentTimeMillis() + " Second try interrupted " + Thread.currentThread().getName());
}
});
lock.lock(); // main thread holds lock
lockTestThread.start(); // start async thread
Thread.sleep(100); // sleep 100 ms
lock.unlock(); // release lock
}
}The first attempt fails because the main thread holds the lock; the second attempt succeeds after the main thread releases the lock within the 3‑second timeout, demonstrating how timeout locks can control wait periods effectively.
Fair vs Non‑fair Locks
ReentrantLock provides a constructor ReentrantLock(boolean fair). Passing true creates a fair lock where threads acquire the lock in FIFO order; passing false (or using the no‑arg constructor) creates a non‑fair lock that may grant the lock to a thread that arrives later, offering higher throughput.
Best Practices
Always manage lock acquisition and release explicitly; place unlock() in a finally block to guarantee release.
Avoid deadlocks by not mixing different lock types, limiting the number of locks held simultaneously, and using lockInterruptibly() when you need to respond to interruptions.
Prefer the default non‑fair lock for better performance unless strict ordering is required.
Be cautious with reentrancy: unnecessary re‑entry increases lock contention and can introduce deadlock risk if exceptions prevent proper release.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
