Fundamentals 8 min read

Deep Dive into Java Concurrency: Inside the AQS Source Code (Part 4)

This article provides a thorough technical walkthrough of Java's AbstractQueuedSynchronizer, covering its core state and CLH queue structures, exclusive and shared lock acquisition/release processes, Condition implementation, and interview-ready explanations of its underlying mechanisms.

Coder Trainee
Coder Trainee
Coder Trainee
Deep Dive into Java Concurrency: Inside the AQS Source Code (Part 4)

Introduction

In the previous three installments the author covered JMM, synchronized, volatile, and CAS as the low‑level building blocks of Java concurrency. This fourth part turns to the core framework that powers most synchronizers: AbstractQueuedSynchronizer (AQS).

What Is AQS?

AQS is the foundational framework for synchronizers in the java.util.concurrent package. It maintains a volatile int state and a CLH (Craig, Landin, and Hagersten) queue, which together implement the basic logic for blocking locks and other synchronizers.

Core Data Structures

The key fields are: volatile int state – the synchronization state, updated via CAS. For example, state = 0 means unlocked in ReentrantLock, a positive value is the re‑entrance count, the count value in CountDownLatch, or the remaining permits in Semaphore.

The Node class represents a waiting thread in the CLH queue. Important constants are CANCELLED = 1, SIGNAL = -1, CONDITION = -2, and PROPAGATE = -3. Each node holds waitStatus, prev, next, and the associated Thread.

Core Methods

acquire(int arg) – tries tryAcquire(arg); if it fails, the thread is enqueued via addWaiter(Node.EXCLUSIVE) and then spins in acquireQueued. If the thread is interrupted while waiting, it self‑interrupts before returning.

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

addWaiter(Node mode) – creates a new Node for the current thread, attempts a fast‑path CAS insertion at the tail, and falls back to the full enq(node) algorithm when the fast path fails.

private Node addWaiter(Node mode) { 
    Node node = new Node(Thread.currentThread(), mode); 
    Node pred = tail; 
    if (pred != null) { 
        node.prev = pred; 
        if (compareAndSetTail(pred, node)) { 
            pred.next = node; 
            return node; 
        } 
    } 
    enq(node); 
    return node; 
}

acquireQueued(Node node, int arg) – repeatedly checks the predecessor; when the predecessor becomes the head, it retries tryAcquire(arg). If acquisition fails, the thread may be parked until it is unblocked.

final boolean acquireQueued(final Node node, int arg) { 
    boolean failed = true; 
    try { 
        boolean interrupted = false; 
        for (;;) { 
            Node p = node.predecessor(); 
            if (p == head && tryAcquire(arg)) { 
                setHead(node); 
                p.next = null; 
                failed = false; 
                return interrupted; 
            } 
            if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) { 
                interrupted = true; 
            } 
        } 
    } finally { 
        if (failed) cancelAcquire(node); 
    } 
}

release(int arg) – invokes tryRelease(arg); if successful, it wakes the successor of the head node.

public final boolean release(int arg) { 
    if (tryRelease(arg)) { 
        Node h = head; 
        if (h != null && h.waitStatus != 0) 
            unparkSuccessor(h); 
        return true; 
    } 
    return false; 
}

Shared Mode

In shared mode the framework uses acquireShared and releaseShared. The key difference is that a successful acquisition can be followed by other threads acquiring the same lock, and releasing propagates wake‑ups to subsequent nodes. The article shows a CountDownLatch example where await() calls acquireShared and threads are released when the count reaches zero.

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

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

Condition Implementation

The inner class ConditionObject implements the Condition interface. It maintains its own wait queue ( firstWaiter, lastWaiter) and provides await() (release lock, enqueue, block) and signal() (move a node to the sync queue and wake it).

public class ConditionObject implements Condition { 
    private Node firstWaiter; 
    private Node lastWaiter; 
    
    public final void await() throws InterruptedException { 
        // 1. enqueue, 2. release lock, 3. block, 4. reacquire 
    } 
    
    public final void signal() { 
        // move first waiter to sync queue and unpark 
    } 
}

Interview‑Ready Summary

Core idea: AQS combines state and a CLH queue to build synchronizers. state is a volatile int modified by CAS; subclasses implement tryAcquire / tryRelease to manipulate it.

The CLH queue is a doubly‑linked list of waiting Node objects.

AQS supports both exclusive and shared modes. acquire / release are template methods; the actual lock logic lives in subclass‑provided tryAcquire / tryRelease.

Built‑in ConditionObject supplies the classic wait/notify mechanism.

Next Episode Preview

The upcoming part will explore ReentrantLock and Condition in depth, covering fair vs. non‑fair locks, re‑entrancy principles, practical producer‑consumer scenarios, and more.

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.

javaConcurrencyLockAQSConditionAbstractQueuedSynchronizer
Coder Trainee
Written by

Coder Trainee

Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.

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.