Fundamentals 7 min read

AQS Unveiled: State, CLH Queue, and Template Method in Java Concurrency

This article explains Java's AbstractQueuedSynchronizer (AQS) core model using a service counter analogy, detailing how the state variable and CLH queue manage thread synchronization, the template method pattern separating queuing logic from acquisition rules, and how LockSupport.park/unpark enable efficient thread blocking and waking, illustrated with ReentrantLock and CountDownLatch examples.

Lobster Programming
Lobster Programming
Lobster Programming
AQS Unveiled: State, CLH Queue, and Template Method in Java Concurrency

AQS (AbstractQueuedSynchronizer), implemented by Doug Lea in JDK 1.5, serves as the foundational framework for locks and synchronizers in the java.util.concurrent (JUC) package. Common classes like ReentrantLock, Semaphore, and CountDownLatch all build on AQS despite their differing functionalities.

Core Model: State and CLH Queue

The article uses a government service counter analogy: a single open counter with a waiting area. The AQS state variable acts like the counter's status indicator: private volatile int state; When state = 0, the counter is free and the next waiting thread (user) is called. When a thread acquires the lock, state becomes 1, marking the counter busy; subsequent threads must wait in the waiting area, which corresponds to the CLH (Craig, Landin, and Hagersten) queue — a doubly linked list where each waiting thread is wrapped as a Node. The queue operates on a first-in-first-out basis.

CLH queue diagram showing doubly linked list of Node objects
CLH queue diagram showing doubly linked list of Node objects

The full thread flow: a thread checks state; if 0, it sets state = 1 and proceeds. If state = 1, the thread is packaged into a Node and appended to the CLH queue tail.

Thread acquisition flow diagram
Thread acquisition flow diagram

Design: Template Method Pattern

Doug Lea applied the template method pattern: AQS as the parent class handles all complex, reusable logic — thread queuing, enqueueing, dequeueing, blocking, and waking — while subclasses only implement simple rule-specific methods: tryAcquire() for attempting acquisition and tryRelease() for attempting release, which modify the state value.

Template method pattern: AQS parent class handles queuing, subclasses implement tryAcquire/tryRelease
Template method pattern: AQS parent class handles queuing, subclasses implement tryAcquire/tryRelease

Two subclasses illustrate different rules:

ReentrantLock (exclusive lock) : tryAcquire() succeeds only when state == 0, then sets state = 1, preventing others from acquiring.

CountDownLatch (shared lock) : Threads pass only when state counts down to zero.

Efficient Blocking and Waking with LockSupport

Threads in the queue do not spin in a busy loop. Instead, AQS uses LockSupport.park() to request the OS to suspend the thread, consuming virtually no CPU. When the lock is released, the holder calls LockSupport.unpark(thread) to wake the next queued thread. This scheduling is performed by the OS kernel.

LockSupport park/unpark mechanism
LockSupport park/unpark mechanism

Complete Lock Acquisition and Release Process

Thread A arrives, sees state = 0, sets state = 1, executes business logic.

Thread B arrives, sees state = 1, fails to acquire.

AQS wraps Thread B into a Node and enqueues it.

AQS calls LockSupport.park(); Thread B sleeps.

Thread A finishes, sets state = 0.

AQS detects waiting threads, calls LockSupport.unpark(thread).

Thread B wakes, sees state = 0, sets state = 1, executes its logic.

Step-by-step lock acquisition and release flow
Step-by-step lock acquisition and release flow

Summary

AQS uses state to indicate lock availability ( state = 0 means acquirable) and the CLH queue as the waiting area for threads that cannot acquire the lock.

AQS employs the template method pattern: parent class manages queuing, subclasses define acquisition/release rules.

AQS leverages LockSupport.park() and LockSupport.unpark(thread) for efficient, OS-kernel-level thread blocking and waking.

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.

AQSReentrantLockJava ConcurrencyLockSupportCountDownLatchAbstractQueuedSynchronizerCLH QueueTemplate Method Pattern
Lobster Programming
Written by

Lobster Programming

Sharing insights on technical analysis and exchange, making life better through technology.

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.