Memory Models & Atomics Ordering — Senior¶
At senior level, focus on this question:
When is relaxed atomic ordering safe to use, and when does it risk subtle bugs?
Prerequisite: middle.md.
Relaxed: atomicity guaranteed, ordering NOT guaranteed¶
Relaxed ordering guarantees the operation itself is atomic (no torn reads/writes, no lost updates on the counter itself) but makes no promise about how this operation's effects order relative to any other memory operation in the program — no happens-before edge is established at all, unlike acquire/release (middle.md).
When relaxed is safe: pure counters with no other dependent state¶
A simple statistics counter (total requests served) where you only care about the eventual, correct total — not "did thread A's increment happen before or after thread B's" — is a textbook safe use of relaxed ordering: correctness (atomic increments, no lost updates) is preserved; ordering simply doesn't matter for this use case.
When relaxed is NOT safe: publishing data alongside a flag¶
// WRONG: relaxed ordering gives NO guarantee that data is visible
// by the time ready is observed as true
data = 42;
ready.store(true, std::memory_order_relaxed); // BUG: should be RELEASE
🎯 Senior takeaway: relaxed ordering is a genuine, meaningful optimization — but only for operations where no other memory access depends on establishing a happens-before relationship through it. The moment you're using an atomic variable to signal "it's now safe to read this other data," you need acquire/release (or stronger), not relaxed — using relaxed there silently reintroduces
junior.md's reordering bug, disguised as "using an atomic, so it should be safe."
Test yourself¶
- Why is relaxed ordering safe for a simple statistics counter but unsafe for a "ready" flag guarding access to other data?
- What specifically does relaxed ordering guarantee, and what does it explicitly NOT guarantee?
- Diagnose why a program using a relaxed atomic
readyflag to guard reading a separatedatavariable can intermittently read stale data, even though the atomic operations themselves are "correct" (no torn reads/lost updates onreadyitself).
Continue to professional.md to compare the Java, C++, and Go memory models' formal guarantees.