Fundamentals 17 min read

Understanding and Implementing the CLH Spin Lock in Java

This article explains the concepts of spin locks and mutexes, introduces the CLH lock as a fair spin lock used in Java's AbstractQueuedSynchronizer, and provides a detailed step‑by‑step walkthrough of its initialization, lock acquisition, release, testing, and common pitfalls with illustrative code and diagrams.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding and Implementing the CLH Spin Lock in Java

The article begins by distinguishing spin locks from traditional mutexes, noting that spin locks keep a thread busy‑waiting (busy‑waiting) while mutexes put the thread to sleep (sleep‑waiting), making spin locks suitable for short‑duration critical sections.

It then introduces the CLH lock, a fair spin lock invented by Craig, Landin, and Hagersten, and explains that it forms the basis of Java's AbstractQueuedSynchronizer (AQS), which is essential for mastering Java concurrency utilities.

CLH Lock Initialization

The implementation defines an inner CLHNode class with a volatile boolean locked field. Three key fields are used: an AtomicReference<CLHNode> tailNode to hold the tail of the logical queue, and two ThreadLocal<CLHNode> variables ( predNode and curNode ) to store each thread's predecessor and current node. The constructor creates an initial empty node and sets up the thread‑local variables.

Lock Acquisition (lock method)

The lock() method retrieves the thread’s current node, marks it as locked, atomically swaps it with the tail to obtain the predecessor node, stores the predecessor in predNode , and then spins while preNode.locked is true. When the predecessor releases the lock, the spinning thread proceeds and prints a success message.

Lock Release (unLock method)

The unLock() method fetches the current node, sets its locked flag to false, prints a release message, and creates a fresh CLHNode for the thread’s next lock acquisition, improving garbage‑collection efficiency.

Why a New Node Is Needed

If the new node creation is omitted, a thread that re‑enters lock() after unlocking will see its predecessor still marked as locked, causing it to spin forever. The fresh node breaks this stale link.

Testing the CLH Lock

A simple test spawns 100 threads, each incrementing a shared counter under the CLH lock. After a short pause, the final counter value matches the expected total, demonstrating correct mutual exclusion even under high contention.

Conclusion

The article summarizes the learning points: the difference between spin and mutex locks, the purpose of the CLH lock, and a hands‑on implementation that prepares readers for deeper exploration of AQS and other Java concurrency mechanisms.

JavaconcurrencymultithreadingAQSspinlockCLHLockLockAlgorithm
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

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