Why use a ReentrantLock if one can use synchronized(this)?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
When managing synchronization in multi-threaded Java applications, developers traditionally rely on the synchronized keyword to control access to shared resources. As straightforward and effective as synchronized blocks or methods can be, Java 5 introduced a more flexible and feature-rich alternative known as ReentrantLock. This lock mechanism, part of the java.util.concurrent.locks package, offers advanced capabilities for thread synchronization that go beyond what the synchronized approach can provide.
Understanding synchronized
Firstly, a brief overview of the synchronized mechanism is essential. It’s built into the Java language and provides a simple and automatic way to achieve mutual exclusion. When a thread enters a synchronized block or method, it automatically acquires a lock associated with the object or class referenced in the synchronized statement. Other threads attempting to enter the locked block or method are blocked until the lock is released.
The simplicity of synchronized is also accompanied by some limitations:
- Intrinsic Locks: Synchronization is based on the intrinsic locks or monitor locks, which means every object has an intrinsic lock associated with it. If a thread needs more flexibility on how locks are held or released,
synchronizedmay fall short. - Scope: The
synchronizedkeyword does not allow the granularity of lock management (such as attempting to lock without waiting). - Interruptibility: Threads waiting for entry into a synchronized block cannot be interrupted (i.e., there is no way to timeout or cancel the lock acquisition).
Why Consider ReentrantLock?
ReentrantLock is a class from Java’s java.util.concurrent.locks package, which provides a lock implementation with the same basic mutual exclusion properties as implicit monitors but with extended capabilities:
1. Lock Interruption
While a thread waits on a ReentrantLock, it can be interrupted. This is an important feature in scenarios where you want to cancel or abort tasks that are blocked, awaiting a lock.
2. Try Lock with Timeout
ReentrantLock allows threads to attempt to acquire a lock but give up if the lock has not been acquired within a certain timeframe. This is critical in preventing resource starvation and ensuring system responsiveness.
3. Fairness Policy
Unlike synchronized, which does not guarantee any specific order of access (generally it's the thread scheduler’s task), ReentrantLock can be constructed with a fairness policy. Fair locks assure that the longest-waiting thread gets the lock next, which may be essential for particular applications to prevent livelock or thread starvation.
4. Condition Support
ReentrantLock provides a Condition class that can split object monitors into multiple wait sets, which are essentially queues where threads may wait for specific conditions to happen, rather than a single queue as in intrinsic locks.
5. Lock Ownership
ReentrantLock also allows querying if the lock is being held, and by which thread, which can assist in complex debugging scenarios or more sophisticated synchronization policies.
Practical Example
Consider an application managing reservations which requires a high degree of fairness to prevent queue jumping:
Summary Table
| Feature | synchronized | ReentrantLock |
| Intrinsic Lock | Yes | No |
| Interruptible Lock | No | Yes |
| Timeout | No | Yes |
| Fairness | No | Optional (configurable) |
| Condition Support | No | Yes |
| Lock Status Queries | No | Yes |
In conclusion, while synchronized might be suitable for simple scenarios due to its ease of use and less verbose syntax, ReentrantLock should be considered when you need greater control over lock management or when your application requires highly specific synchronization features. The choice of synchronization mechanism will depend primarily on the specific requirements and complexity of your application's concurrency needs.

