Compare-And-Swap (CAS) in Java with `VarHandle`
Concurrency is hard, but Java gives us powerful tools to make it manageable. One such tool is the Compare-And-Swap (CAS) operation, which lies at the heart of lock-free programming. In this blog post, we’ll explore how CAS works, why it needs to be used in a loop, how VarHandle fits in, and why the volatile keyword is critical.
🧠 What Is CAS?
Compare-And-Swap (CAS) is an atomic instruction used to update a variable only if it hasn't changed since the last time it was read. CAS is the building block of non-blocking algorithms.
CAS requires:
- Memory location (V) — the variable to modify
- Expected value (A) — what the thread believes is currently in V
- New value (B) — the value to write
If V == A, CAS sets V = B and returns true; otherwise it returns false.
🔁 Why CAS Needs a Loop
CAS may fail if another thread modifies the variable between your read and write. That's why CAS is typically wrapped in a retry loop:
do {
oldValue = value.get();
newValue = oldValue + 1;
} while (!value.compareAndSet(oldValue, newValue));
This retry loop ensures eventual success even under contention.
🛠 Using VarHandle for CAS (Java 9+)
Java 9 introduced VarHandle to safely and flexibly perform atomic operations.
✅ Example: Increment with VarHandle
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class Counter {
private volatile int value = 0; // must be volatile
private static final VarHandle VALUE_HANDLE;
static {
try {
VALUE_HANDLE = MethodHandles.lookup()
.findVarHandle(Counter.class, "value", int.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
public void increment() {
int oldVal, newVal;
do {
oldVal = (int) VALUE_HANDLE.getVolatile(this);
newVal = oldVal + 1;
} while (!VALUE_HANDLE.compareAndSet(this, oldVal, newVal));
}
public int get() {
return (int) VALUE_HANDLE.getVolatile(this);
}
}
📌 Why the Field Must Be volatile
Using volatile ensures:
- Visibility: All threads see the most recent value of the variable.
- Happens-before guarantee: Writes before a
volatilewrite are visible to threads reading that variable.
Without
volatile, even thoughcompareAndSetis atomic, other threads might see stale values, leading to incorrect results.
📊 Visual Representation of CAS With VarHandle

In this diagram:
- Thread 1 reads and attempts a CAS update.
- Thread 2 reads concurrently.
volatileensures visibility and proper memory ordering.- CAS may retry if another thread modifies the value before it completes.
🔒 Summary
- CAS is a powerful, low-level primitive for writing lock-free concurrent algorithms.
- It's used in
Atomic*classes,Unsafe, andVarHandle. VarHandleis the modern and safer alternative toUnsafe.- Declaring fields as
volatileis essential to ensure memory visibility and correctness.