How Does Java’s ReentrantLock Work? Inside Fair vs. Non‑Fair Locks
This article explains the inner workings of Java's ReentrantLock, covering its API, the difference between fair and non‑fair modes, the lock acquisition and release algorithms, and how it compares to the built‑in synchronized keyword, complete with code examples and detailed analysis.
Introduction
ReentrantLock is a re‑entrant mutual exclusion lock that offers the same basic semantics as the synchronized statement but with more powerful and flexible features, reducing the likelihood of deadlocks.
API Overview
A re‑entrant mutex lock that behaves like the implicit monitor lock used by synchronized , yet provides additional capabilities such as fairness control.
The lock is owned by the thread that most recently acquired it and has not yet released it. Methods like isHeldByCurrentThread() and getHoldCount() let you inspect the lock state.
1. Acquiring the Lock
Typical usage:
public void lock() {
sync.lock();
}The internal Sync class extends AbstractQueuedSynchronizer (AQS) and has two subclasses: FairSync (fair lock) and NonfairSync (default non‑fair lock).
For the non‑fair lock, the lock() method first tries a fast CAS acquisition; if it fails, it delegates to AQS.acquire(int) which may block the thread.
final void lock() {
// try fast path
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}The tryAcquire(int acquires) implementation for the non‑fair lock looks like this:
protected final boolean tryAcquire(int acquires) {
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
} else if (Thread.currentThread() == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}This method first checks whether the lock state is zero (unlocked). If so, it attempts a CAS to set the state to the requested acquire count. If the current thread already holds the lock, it increments the hold count, allowing re‑entrancy.
2. Releasing the Lock
After the critical section, the lock is released via:
public void unlock() {
sync.release(1);
}The release(int arg) method in AQS calls tryRelease(int):
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}The lock is fully released only when the hold count reaches zero; then the owner thread is cleared and waiting threads may acquire the lock.
3. Fair vs. Non‑Fair Locks
The only difference between the two modes is the additional fairness check in the fair lock’s tryAcquire(int) method:
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}The method hasQueuedPredecessors() returns true if there are waiting threads ahead of the current thread in the FIFO queue, ensuring first‑come‑first‑served acquisition.
4. ReentrantLock vs. synchronized
Both provide the same memory semantics.
ReentrantLock offers additional features: timed try‑lock, interruptible lock acquisition, and multiple Condition objects for finer‑grained waiting.
It allows non‑blocking lock attempts (polling) and can be more performant under high contention.
Lock release must be performed in a finally block to avoid resource leaks.
ReentrantLock supports interrupt handling, which synchronized does not.
Overall, ReentrantLock gives developers more control and flexibility compared to the built‑in synchronized construct.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
