Understanding Java's AbstractQueuedSynchronizer (AQS): Principles, Implementation, and Example
This article explains the core concepts of Java's AbstractQueuedSynchronizer, detailing its internal FIFO queue, state management, exclusive and shared modes, and provides complete code examples for custom lock implementation and usage.
AQS Overview
AQS (AbstractQueuedSynchronizer) is the foundational framework in Java for building locks and synchronizers, offering a simple abstract class that supports exclusive and shared synchronization modes.
Internal Data Structures
AQS maintains a FIFO wait queue implemented as a doubly‑linked list, where each node represents a thread waiting for the lock, and a volatile integer state variable that indicates the lock's current status.
Implementation Details
The state variable is 0 when the lock is free, a positive value when held by a thread, and a negative value when threads are waiting.
Exclusive Mode
In exclusive mode, AQS provides acquire and release methods to lock and unlock.
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}The acquire method first attempts tryAcquire ; if it fails, the thread is enqueued and blocked until the lock is released, at which point the next waiting thread is unparked. The release method calls tryRelease and, on success, wakes the successor.
Shared Mode
Shared mode works similarly but allows multiple threads to hold the lock concurrently. The key methods are acquireShared and doAcquireShared :
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}When acquireShared cannot obtain the lock immediately, the thread is added to the wait queue and blocked until the lock becomes available.
Usage Example
The following example demonstrates a custom lock built on AQS:
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class MyLock extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (getState() == 0) {
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if (getState() == arg) {
setState(0);
setExclusiveOwnerThread(null);
return true;
}
return false;
}
public void lock() {
acquire(1);
}
public void unlock() {
release(1);
}
}And a simple test with two threads incrementing a counter:
public class Main {
private static MyLock lock = new MyLock();
private static int count = 0;
public static void main(String[] args) {
Runnable task = () -> {
lock.lock();
try {
for (int i = 0; i < 10000; i++) {
count++;
}
} finally {
lock.unlock();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("count: " + count);
}
}Conclusion
In summary, AQS provides an abstract lock mechanism in Java based on a wait/notify system, using a state variable and a FIFO queue to manage thread synchronization. It underlies many high‑level synchronizers such as ReentrantLock and Semaphore , and a solid understanding of its internals helps developers implement custom concurrency utilities effectively.
Top Architecture Tech Stack
Sharing Java and Python tech insights, with occasional practical development tool tips.
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.