Fundamentals 7 min read

Understanding Java’s CLH Sync Queue: How AQS Manages Threads

This article explains the internal CLH FIFO queue used by Java's AbstractQueuedSynchronizer, detailing the Node structure, how threads are enqueued with addWaiter and enq methods, and how they are dequeued to acquire synchronization state, complete with code examples and diagrams.

Programmer DD
Programmer DD
Programmer DD
Understanding Java’s CLH Sync Queue: How AQS Manages Threads

Background

In Java's AbstractQueuedSynchronizer (AQS), a CLH (Craig, Landin, and Hagersten) FIFO queue is used to manage thread synchronization. When a thread fails to acquire a lock, it creates a Node representing its wait status and inserts it into this queue.

Node Structure

static final class Node {
    static final Node SHARED = new Node();
    static final Node EXCLUSIVE = null;
    static final int CANCELLED = 1;
    static final int SIGNAL = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;
    volatile int waitStatus;
    volatile Node prev;
    volatile Node next;
    volatile Thread thread;
    Node nextWaiter;
    final boolean isShared() { return nextWaiter == SHARED; }
    Node predecessor() throws NullPointerException {
        Node p = prev;
        if (p == null) throw new NullPointerException();
        return p;
    }
    Node() {}
    Node(Thread thread, Node mode) { this.nextWaiter = mode; this.thread = thread; }
    Node(Thread thread, int waitStatus) { this.waitStatus = waitStatus; this.thread = thread; }
}

1. Enqueueing a Thread (Add to Queue)

The addWaiter(Node mode) method creates a new node for the current thread and attempts a fast-path insertion at the tail. If the fast CAS fails, it falls back to the more robust enq(Node node) method.

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;
}

The enq(Node node) method repeatedly attempts to link the new node at the tail using a CAS loop, initializing the queue head if it is absent.

private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) {
            if (compareAndSetHead(new Node())) {
                tail = head;
            }
        } else {
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}

Both methods rely on compareAndSetTail to ensure thread‑safe insertion.

2. Dequeueing a Thread (Remove from Queue)

When the head node releases the synchronization state, AQS wakes its successor ( next) without using CAS, because only one thread can own the lock at a time. The successor then becomes the new head and attempts to acquire the lock.

Visually, the process follows a simple FIFO pattern: the head node is removed, its next node is unlinked, and the lock handoff proceeds.

Illustrations

CLH queue structure
CLH queue structure
Enqueue process diagram
Enqueue process diagram
Dequeue process diagram
Dequeue process diagram

Conclusion

The CLH queue provides a lock‑free, FIFO ordering mechanism for threads waiting on AQS. Understanding the Node fields, the enqueue logic in addWaiter and enq, and the simple handoff during dequeue helps developers grasp how Java implements fair and non‑fair locks under the hood.

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.

AQSCLH
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.