C · 6 · Advanced / Job-Ready31 / 35 · 89%
C11 Atomics & Memory Ordering
Lock-free counters and the ordering guarantees that make them correct.
Examples: _Atomic, atomic_fetch_add, memory_order
shortcuts: ← prev · → next · M mark
1
Atomic Types
Read-modify-write in one indivisible step.
Example
example
#include <stdatomic.h>
_Atomic int counter = 0;
atomic_fetch_add(&counter, 1); // seq_cst by default
int now = atomic_load(&counter);
atomic_store(&counter, 0);2
Why ++ Is Not Atomic
One line of C is three machine steps.
counter++ (plain int)
| step | op |
|---|---|
| 1 | load |
| 2 | add 1 |
| 3 | store |
atomic_fetch_add
| step | op |
|---|---|
| 1 | lock xadd |
| indivisible | |
| no lost update |
Two threads interleaving the load/add/store lose increments.
3
Memory Orders
Weaker orders are faster but harder to reason about.
Example
example
atomic_fetch_add(&hits, 1, memory_order_relaxed); // counter only
atomic_store(&ready, 1, memory_order_release); // publish
if (atomic_load(&ready, memory_order_acquire)) { } // consumeTIP
Default to seq_cst. Only weaken to acquire/release after you have measured a real bottleneck.
4
Compare-and-Swap
The building block of every lock-free algorithm.
Example
example
int expected = old;
while (!atomic_compare_exchange_weak(&value, &expected, expected + 1)) {
// expected was reloaded with the current value — retry
}Interview question
When is a lock-free structure worse than a mutex?