we use smth like this in Counter class
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();
👉 We don’t directly call compareAndSet()
— but under the hood, incrementAndGet()
uses compareAndSet()
(or CAS instructions) internally!
🧠 Let’s Unpack It
Here’s what actually happens inside AtomicInteger.incrementAndGet()
:
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
And getAndAddInt()
is implemented like this in the Unsafe
class (simplified logic):
public final int getAndAddInt(Object obj, long offset, int delta) {
int prev, next;
do {
prev = getIntVolatile(obj, offset);
next = prev + delta;
} while (!compareAndSwapInt(obj, offset, prev, next));
return prev;
}
🔁 What’s Going On Here:
- Get the current value (
prev
) - Compute new value (
next = prev + delta
) - Try to
compareAndSwap
fromprev
tonext
- If another thread changed it in the meantime → try again (loop)
🎯 So You’re Right:
You don’t see CAS in your own code when you use methods like:
incrementAndGet()
decrementAndGet()
addAndGet()
But the JVM calls compareAndSwap
inside those methods to ensure atomicity.
🤖 CAS vs Synchronized Revisited
Operation | Under the hood | Locking? |
---|---|---|
synchronized block | JVM monitor/lock | ✅ Yes |
AtomicInteger.incrementAndGet() | CAS via Unsafe or VarHandle | ❌ No |