🔄 compareAndSet()
vs weakCompareAndSet()
Both are methods in java.util.concurrent.atomic.*
classes, like AtomicInteger
, AtomicReference
, etc.
They perform Compare-And-Swap (CAS) operations — which are the backbone of lock-free algorithms.
✅ compareAndSet(expectedValue, newValue)
- Checks if the current value equals
expectedValue
. - If yes, sets it to
newValue
atomically. - Returns
true
if successful. - Guaranteed to retry internally if necessary (strong semantics).
AtomicInteger counter = new AtomicInteger(10);
boolean success = counter.compareAndSet(10, 20); // true
This is the one most developers use — it’s safe, consistent, and works reliably across platforms.
⚡ weakCompareAndSet(expectedValue, newValue)
- Does the same logic, but may fail spuriously even if the values are equal.
- May return
false
even if no other thread interfered. - Often used in tight loops, like:
do {
expected = atomic.get();
updated = doSomething(expected);
} while (!atomic.weakCompareAndSet(expected, updated));
It’s faster on some CPUs (especially ARM) that support weaker memory models.
⚠️ Why Would weakCompareAndSet()
Fail Spuriously?
- Hardware-level optimizations and relaxed memory ordering can cause false negatives.
- On certain architectures, a weak CAS is cheaper and can avoid memory fences or retries.
- The method is allowed to fail even when it could succeed — so you must loop around it.
🧪 Summary Table
Feature | compareAndSet() | weakCompareAndSet() |
---|---|---|
Guarantees | Strong CAS | Weak CAS (may fail spuriously) |
Memory semantics | Full memory ordering | Possibly relaxed memory ordering |
Retry needed | Usually not (internal retries) | Yes (should be in a loop) |
Use case | General-purpose CAS | Low-level lock-free loops, fast paths |
🚀 When to Use Which?
Situation | Use |
---|---|
Typical atomic updates | compareAndSet() |
High-performance lock-free loops | weakCompareAndSet() (with retry) |