What is ReentrantLock in Java: Explanation and Example
ReentrantLock in Java is a synchronization tool that allows a thread to lock a resource multiple times without causing a deadlock. It provides more control than the synchronized keyword, such as the ability to try locking without waiting and to interrupt waiting threads.How It Works
Imagine you have a key to a room that you can use to lock the door. If you enter the room and lock the door, you can also lock it again without needing to unlock it first. This is how ReentrantLock works: the same thread can lock the resource multiple times safely.
When a thread locks a ReentrantLock, it gains exclusive access to the resource. If the same thread tries to lock it again, it just increases a count instead of blocking. The thread must unlock the resource the same number of times it locked it to release it fully.
This mechanism helps avoid problems where a thread might accidentally block itself by trying to lock a resource it already holds, which can happen with simpler locks.
Example
This example shows two threads trying to use a ReentrantLock to control access to a shared counter. The lock ensures only one thread changes the counter at a time.
import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { private final ReentrantLock lock = new ReentrantLock(); private int counter = 0; public void increment() { lock.lock(); // Acquire the lock try { counter++; System.out.println(Thread.currentThread().getName() + " incremented counter to " + counter); } finally { lock.unlock(); // Release the lock } } public static void main(String[] args) { ReentrantLockExample example = new ReentrantLockExample(); Runnable task = () -> { for (int i = 0; i < 3; i++) { example.increment(); try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }; Thread t1 = new Thread(task, "Thread-1"); Thread t2 = new Thread(task, "Thread-2"); t1.start(); t2.start(); } }
When to Use
Use ReentrantLock when you need more control over locking than what synchronized provides. For example, if you want to try locking without waiting forever, or if you want to interrupt a thread waiting for a lock.
It is useful in complex programs where threads share resources and you want to avoid deadlocks or improve performance by controlling lock fairness.
Real-world cases include managing access to shared data structures, coordinating threads in server applications, or implementing custom synchronization policies.
Key Points
- ReentrantLock allows the same thread to lock multiple times safely.
- It offers advanced features like tryLock() and interruptible lock acquisition.
- It requires explicit unlocking in a
finallyblock to avoid deadlocks. - It is more flexible than
synchronizedbut needs careful use.