Understanding Java CAS: How Compare‑And‑Swap Powers Lock‑Free Concurrency
This article explains the Compare‑And‑Swap (CAS) primitive, its three operands, how Java's Unsafe class implements CAS methods, the internal workings of AtomicInteger, common pitfalls like spinning, single‑variable limits and the ABA problem, and the enhancements introduced in Java 8.
Compare‑And‑Swap (CAS)
CAS is a hardware‑level synchronization primitive that atomically updates a memory location only when its current value matches an expected old value. It enables lock‑free coordination between threads.
Memory value V Expected old value A New value B If V == A, the operation atomically writes B to V; otherwise it does nothing and the caller typically retries.
Java Unsafe CAS API
The class sun.misc.Unsafe provides low‑level CAS operations used by the J.U.C. atomic classes:
compareAndSwapInt(Object obj, long offset, int expected, int newValue) compareAndSwapLong(Object obj, long offset, long expected, long newValue)J.U.C. atomic wrappers
Below is the core of java.util.concurrent.atomic.AtomicInteger, which builds on Unsafe:
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// Unsafe instance used for CAS operations
private static final Unsafe unsafe = Unsafe.getUnsafe();
// Memory offset of the "value" field within the object
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// The actual integer value, declared volatile for visibility
private volatile int value;
}Key fields: unsafe – provides direct memory access and CAS primitives. valueOffset – the offset used by Unsafe to locate the value field. value – the stored integer, marked volatile so that updates are visible to all threads.
The incrementAndGet method delegates to Unsafe.getAndAddInt:
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
} Unsafe.getAndAddIntimplements a CAS loop:
public final int getAndAddInt(Object obj, long offset, int delta) {
int v;
do {
v = getIntVolatile(obj, offset);
} while (!compareAndSwapInt(obj, offset, v, v + delta));
return v;
}The loop repeatedly reads the current value, attempts a compareAndSwapInt, and retries until the update succeeds. This embodies the classic “compare‑then‑update” pattern, relying on the CPU’s cmpxchg instruction for atomicity.
Limitations of CAS
Spinning overhead
When many threads contend for the same variable, repeated CAS failures cause busy‑waiting (spinning). The threads consume CPU cycles while repeatedly invoking the CAS instruction, which can degrade performance under high contention.
Single‑variable guarantee
CAS provides atomicity for a single memory location only. To modify multiple related values atomically, Java offers AtomicReference (or custom holder objects) so that the whole reference can be swapped in one CAS operation.
ABA problem
If a location changes from A to B and back to A, a plain CAS cannot detect the intermediate change; it sees the expected value A and proceeds, potentially missing a logical update. The common remedy is to attach a version stamp to the value. Java 1.5 introduced AtomicStampedReference, whose compareAndSet checks both the reference and its stamp before performing the update.
Java 8 high‑performance accumulators and adders
Doug Lea added a family of classes that reduce contention for frequently updated counters by partitioning the state into multiple cells. Each thread updates a separate cell, and the total is computed only when needed.
Accumulators
Accumulators perform a user‑supplied associative operation (e.g., sum, max) on a set of values.
Counters (Adders)
Adders are specialized for addition. They maintain a set of cells (one per CPU core or thread) to avoid false sharing.
When the total value is required, the cells are summed; otherwise, each thread updates its own cell with minimal contention, providing better scalability for high‑frequency updates with infrequent reads.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaEdge
First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
