Understanding Java's AbstractQueuedSynchronizer (AQS) Framework and Its Source Code
This article provides a comprehensive overview of Java's AbstractQueuedSynchronizer (AQS), explaining its design, exclusive and shared synchronization modes, key methods such as acquire, release, and their implementations, and demonstrates a simple Mutex application with detailed code analysis.
When discussing concurrency in Java, ReentrantLock inevitably leads to AbstractQueuedSynchronizer (AQS), an abstract queue‑based synchronizer that forms the backbone of many synchronization utilities such as ReentrantLock, Semaphore, and CountDownLatch.
AQS maintains a volatile int state representing the shared resource and a FIFO wait queue for threads that cannot acquire the resource immediately. It supports two sharing modes: Exclusive (only one thread can hold the resource, e.g., ReentrantLock) and Share (multiple threads can hold it simultaneously, e.g., Semaphore, CountDownLatch).
Custom synchronizers only need to implement the state‑access methods ( getState(), setState(), compareAndSetState()) and the appropriate acquisition/release hooks:
isHeldExclusively() tryAcquire(int)/ tryRelease(int) for exclusive mode tryAcquireShared(int) / tryReleaseShared(int) for shared mode
For example, the acquire(int arg) method (exclusive mode) works as follows:
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}The flow is:
Attempt to acquire the resource directly via tryAcquire.
If it fails, enqueue the thread at the tail of the wait queue with addWaiter.
Enter acquireQueued to park the thread until it is unparked.
After successful acquisition, perform a self‑interrupt to preserve the interrupt status.
Similarly, the release(int arg) method releases the resource and wakes the next waiting thread:
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}In shared mode, acquireShared(int) and releaseShared(int) follow analogous logic, with the return value of tryAcquireShared indicating success, partial success, or failure, and doReleaseShared handling propagation to subsequent waiting threads.
The article also presents a simple application: a non‑reentrant Mutex built on AQS. The Mutex defines its own inner Sync class that implements tryAcquire and tryRelease, while the outer class exposes lock and unlock operations.
Overall, the piece demystifies AQS by breaking down its core framework, detailing the essential methods, and illustrating how custom synchronizers like Mutex can be constructed using this powerful concurrency primitive.
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.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
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.
