Understanding Java's AbstractQueuedSynchronizer: Locks, Queues, and State Management

This article explains Java's AbstractQueuedSynchronizer (AQS) framework, covering its FIFO queue mechanism, lock acquisition and release processes for exclusive and shared modes, state handling, and the abstract methods developers must implement to build custom synchronizers.

JavaEdge
JavaEdge
JavaEdge
Understanding Java's AbstractQueuedSynchronizer: Locks, Queues, and State Management

AbstractQueuedSynchronizer (AQS) Overview

AQS provides a FIFO‑based framework for implementing synchronizers such as exclusive locks, shared locks, semaphores, and events. It separates two responsibilities: (1) manipulating the state field that represents the lock’s logical state, and (2) managing a wait queue and the blocking/unblocking of threads. Subclasses implement the abstract methods that operate on state; AQS supplies the queue handling logic.

AQS itself does not implement any public synchronization interface; it only offers low‑level methods like acquireInterruptibly that concrete synchronizers invoke.

MESA Monitor Model in Java

Java follows the MESA monitor model, which guarantees that accesses to shared fields and methods are thread‑safe. In AQS the model is simplified to a single condition variable and a single FIFO wait queue. The queue is used both for exclusive acquisition and, via ConditionObject, for condition‑await semantics.

Acquiring an Exclusive Lock

Basic acquisition (ignoring interrupts)

public final void acquire(int arg) {
    if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
tryAcquire

is abstract; a subclass defines the actual lock‑state transition. If acquisition fails, the thread is enqueued with addWaiter and then spins in acquireQueued until it becomes the head and can obtain the lock.

Queue node states

CANCELLED (1) : node was cancelled because of timeout or interruption.

SIGNAL (-1) : predecessor will signal this node when it releases.

CONDITION (-2) : used by ConditionObject for condition‑await.

PROPAGATE (-3) : shared‑mode propagation flag.

0 : intermediate state after predecessor has signaled.

Interrupt‑responsive acquisition

acquireInterruptibly(int arg)

checks the thread’s interrupt status before attempting to acquire and during the queue spin. If an interrupt is observed, it throws InterruptedException and aborts.

Acquisition with timeout

tryAcquireNanos(int arg, long nanosTimeout)

adds a timeout check. Each failed spin decrements the remaining time; before parking the thread it compares the remaining timeout with a spin‑threshold (≈1 ns). Parking is performed via LockSupport.parkNanos.

Releasing an Exclusive Lock

Release consists of two steps:

Invoke the abstract tryRelease(int arg) implemented by the subclass to modify state.

Wake the successor node using unparkSuccessor. The method requires a non‑null head and a non‑zero waitStatus. If the immediate successor’s waitStatus ≤ 0, it is unparked directly; otherwise the queue is scanned backwards to find the nearest viable node.

Acquiring a Shared Lock

Basic shared acquisition (ignoring interrupts)

public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}
tryAcquireShared

returns an int indicating the result:

Negative – acquisition failed; the thread must enqueue.

Zero – acquisition succeeded but no further shared acquires will succeed.

Positive – acquisition succeeded and additional shared acquires may also succeed; wake‑up propagation is required.

If the call returns a negative value, the thread is added to the queue (nodes marked with nextWaiter == SHARED) and spins in doAcquireShared until it can acquire.

Interrupt‑responsive shared acquisition

acquireSharedInterruptibly(int arg)

checks interrupt status before acquisition and during the spin, throwing InterruptedException when an interrupt is observed.

Shared acquisition with timeout

tryAcquireSharedNanos(int arg, long nanosTimeout)

mirrors the exclusive timeout logic: each failed attempt checks the remaining time, and before parking the thread it compares the timeout with the spin‑threshold. Parking uses LockSupport.parkNanos.

Releasing a Shared Lock

public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

After tryReleaseShared succeeds, doReleaseShared performs a spin that propagates wake‑ups through the queue. Propagation continues while the head’s waitStatus is –1, 0, or –3 and at least two nodes remain in the queue.

Abstract Methods Required by Subclasses

tryAcquire(int arg)

– exclusive lock acquisition. tryRelease(int arg) – exclusive lock release. tryAcquireShared(int arg) – shared lock acquisition. tryReleaseShared(int arg) – shared lock release.

Subclasses may also override isHeldExclusively() to indicate exclusive ownership.

Key Takeaways

AQS implements a reusable FIFO queue template that underlies most Java synchronizers. The waitStatus field of each node encodes whether the thread should wait, be signaled, or propagate wake‑ups, enabling the construction of exclusive locks, shared locks, semaphores, and condition objects with consistent blocking semantics.

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.

JavaconcurrencySynchronizationAQSexclusive lockshared lock
JavaEdge
Written by

JavaEdge

First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.

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.