Reentrant Lock
About
A Reentrant Lock is an explicit locking mechanism provided by java.util.concurrent.locks.ReentrantLock
. Unlike the intrinsic locks (monitor locks) obtained via the synchronized
keyword, ReentrantLock provides more flexibility and advanced control over thread synchronization.
A Reentrant Lock is a type of mutual exclusion (mutex) lock that allows the same thread to acquire the lock multiple times without causing itself to block. The lock maintains a hold count, increasing when the thread re-acquires it and decreasing when it releases it. When the count reaches zero, the lock is fully released.
This behavior is useful in recursive method calls where a thread that already holds the lock can re-enter the same locked section without deadlocking itself.
Why Use Reentrant Locks?
Provides More Control – Unlike
synchronized
, you can manually lock/unlock.Supports Fairness Policy – You can choose a fair lock that grants access in a FIFO order.
Interruptible Locking – A thread can be interrupted while waiting for the lock.
Timeout Support – The lock can be acquired with a timeout to prevent indefinite blocking.
Multiple Condition Variables – Supports advanced wait-notify mechanisms via
Condition
objects.
How to Use Reentrant Lock?
Basic Locking and Unlocking
In this example,
The lock is explicitly acquired and released.
The
finally
block ensures the lock is always released to prevent deadlocks.Unlike
synchronized
, we can handle situations where the lock is unavailable.
Reentrant Behavior
A thread can acquire the lock multiple times without blocking itself.
In this example,
Same thread can re-enter a locked section without deadlocking itself.
The hold count increases with every re-entry and decreases when unlocking.
Try Locking with Timeout
To avoid indefinite blocking, a thread can attempt to acquire a lock with a timeout.
Interruptible Locking
A thread waiting for a lock can be interrupted.
If
lockInterruptibly()
is used, the waiting thread can be interrupted.Useful in applications where cancellation of tasks is required.
If
lockInterruptibly()
is not used, and insteadlock()
is used, then the waiting thread cannot be interrupted while it is blocked, meaning it will remain in the waiting state indefinitely until it acquires the lock.
Fair vs. Non-Fair Locks
By default, ReentrantLock is unfair, meaning the lock is not granted in a strict queue order. This can lead to starvation.
Fair Lock Example (FIFO Order)
Ensures FIFO order – The longest waiting thread gets the lock next.
Can reduce performance due to increased context switching.
Unfair Lock Example (Default)
Threads may not get the lock in order.
Higher throughput but risk of starvation.
ReentrantLock vs. Synchronized
Locking & Unlocking
Manual (lock()
and unlock()
)
Automatic
Fairness
Supports fair locking
Always unfair
Interruptibility
Can be interrupted
Cannot be interrupted
Timeout Support
tryLock()
prevents indefinite blocking
No timeout support
Multiple Conditions
Uses Condition
objects
Uses wait()/notify()
Last updated
Was this helpful?