Fundamentals 11 min read

Demystifying Java’s AbstractQueuedSynchronizer: How Locks Work Under the Hood

This article explains the internal design of Java's AbstractQueuedSynchronizer (AQS), covering its state management, FIFO sync queue, node structure, exclusive lock acquisition and release processes, and key helper methods, with detailed diagrams from JDK 8 implementation.

Programmer DD
Programmer DD
Programmer DD
Demystifying Java’s AbstractQueuedSynchronizer: How Locks Work Under the Hood

What is AQS?

AbstractQueuedSynchronizer (AQS) is a framework created by Doug Lea that provides the foundation for building locks, semaphores, events and other synchronizers in java.util.concurrent. Core classes such as ReentrantLock, ReentrantReadWriteLock, CountDownLatch and many others delegate their core behavior to AQS.

How AQS Works Internally (JDK 8)

AQS maintains an int field state that represents the synchronization state and a FIFO double‑linked queue (the “sync queue”) of Node objects. When a thread fails to acquire the lock it creates a node, appends it to the tail of the queue and blocks until it is signalled.

Each node stores:

A reference to the waiting thread

The thread’s wait status (e.g., SIGNAL, CANCELLED)

Links to predecessor and successor nodes

A mode flag indicating exclusive or shared acquisition

The queue always has a head node (the current owner) and a tail node (the most recent waiter). Threads that cannot obtain the lock are added to the tail; when the owner releases the lock, it wakes the successor.

Exclusive Lock Acquisition

The acquisition starts with acquire(int arg), which calls the subclass’s tryAcquire(arg). The fast path is:

If state == 0 and hasQueuedPredecessors() returns false, a CAS updates state and the thread becomes the exclusive owner.

If the CAS fails or there are queued predecessors, the thread is enqueued via addWaiter(Node.EXCLUSIVE) and then repeatedly invokes acquireQueued(node, arg) until it can acquire the lock or is interrupted.

Inside acquireQueued the thread:

Checks whether its predecessor is the head; if not, it may park.

Uses shouldParkAfterFailedAcquire to examine the predecessor’s waitStatus (‑1 means the predecessor is ready to signal).

If parking is required, it calls LockSupport.park and later checks for interruption.

If the thread finally acquires the lock, it becomes the new head node; otherwise it remains in the queue.

Exclusive Lock Release

When the owning thread finishes its critical section it calls release(int arg). If tryRelease(arg) returns true, the head node’s waitStatus is examined. If it is non‑zero, the successor node is unparked via LockSupport.unpark, allowing the next thread to attempt acquisition.

Key Helper Methods

addWaiter(Node mode)

– creates a node, tries to link it at the tail with a CAS, or falls back to enq(node) if the CAS fails. enq(Node node) – spins until the node becomes the tail, handling the case of an initially empty queue. shouldParkAfterFailedAcquire(Node pred, Node node) – inspects pred.waitStatus to decide whether the current thread should block. parkAndCheckInterrupt() – uses LockSupport.park to suspend the thread and records any interruption.

Summary

The exclusive acquisition path consists of a fast‑path CAS on state, followed by queue insertion, spin‑then‑park loops, and careful handling of predecessor status to ensure correct hand‑off of ownership. Release simply resets state and wakes the next node, completing the lock cycle.

References

Doug Lea, Java Concurrency in Practice

Fang Tengfei, Wei Peng, Cheng Xiaoming, Java Concurrency Programming Art

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyJDK8LockAQSAbstractQueuedSynchronizer
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.