Atomic operations are instructions that execute indivisibly — no other thread can observe a partial result. They are the foundation for all synchronization primitives.
Why Atomicity Matters
// Non-atomic: two threads reading/writing simultaneously
counter++; // Actually: read counter, increment, write counter
// Thread A reads 5, Thread B reads 5
// Thread A writes 6, Thread B writes 6
// Final: 6 (should be 7!)
With an atomic operation:
__sync_fetch_and_add(&counter, 1); // Guaranteed: final = 7
Compare-and-Swap (CAS)
CAS is the most important atomic primitive. It’s used to build all lock-free data structures.
CAS(address, expected, new):
if *address == expected:
*address = new
return true
else:
return false
The key property: CAS succeeds only if the memory hasn’t changed since you last read it. If another thread modified it, CAS fails and you retry.
Lock-Free Increment (using CAS)
void atomic_increment(int *value) {
int old;
do {
old = *value;
} while (!CAS(value, old, old + 1));
}
If another thread modifies *value between reading old and CAS, the CAS fails and we retry. No lock needed — just a loop.
Other Atomic Operations
| Operation | What it does |
|---|---|
| Test-and-Set (TAS) | Set to 1, return old value |
| Fetch-and-Add (FAA) | Add value, return old value |
| Load-Linked / Store-Conditional (LL/SC) | CAS variant, no ABA problem |
| Exchange | Swap a value atomically |
The ABA Problem
Thread 1 reads value A from address
Thread 2 changes A → B → A (back to A, but structure changed)
Thread 1's CAS succeeds — but the world has changed
Solution: Use tagged pointers (ABA counter) or LL/SC instruction.
Q: What is an atomic operation?
A: An operation that appears to execute in a single step from the perspective of other threads. No thread can observe the operation partially complete. Hardware guarantees this at the instruction level (e.g., cmpxchg on x86).
Q: How does Compare-and-Swap work?
A: CAS(addr, expected, new) checks if *addr == expected. If so, sets *addr = new and returns true. Otherwise returns false. The check-and-set is atomic — no other thread can interleave between the comparison and the store.
Q: What is the ABA problem?
A: CAS can’t detect if a value changed from A to B and back to A. The CAS succeeds, but the underlying structure might have changed (e.g., a freed node was reused). Solved with tagged pointers (add a version counter to the pointer) or Load-Linked/Store-Conditional instructions.
Q: What is lock-free programming?
A: Using atomic operations (CAS, FAA) instead of locks to synchronize shared data. No thread can block another — progress is guaranteed even if a thread is suspended. Harder to write correctly but eliminates deadlocks, priority inversion, and contention.
Premium Content
Unlock Atomic Operations & Compare-and-Swap and all premium lessons with a subscription.
From ₹199.99/year — See plans