Concurrency Fundamentals • Memory Models & OrderingHard⏱️ ~3 min
Memory Ordering Modes
Key Insight
C++ offers different memory orderings trading safety for performance. Stronger ordering = more guarantees = slower.
Memory Ordering Spectrum
Relaxed (memory_order_relaxed)
Only guarantees atomicity. No ordering constraints. Use for counters where you just need accurate final value, not intermediate visibility.
Acquire/Release
Acquire (on load): No reads/writes after this can be reordered before it. Acquire the lock, then access data.
Release (on store): No reads/writes before this can be reordered after it. Finish with data, then release the lock.
Sequential Consistency (memory_order_seq_cst)
The default and strongest. All threads see all operations in the same order. Easiest to reason about but has highest cost. Most developers should use this.
Advice: Start with seq_cst. Only weaken if profiling shows it is a bottleneck AND you deeply understand the implications.
💡 Key Takeaways
✓Relaxed ordering: only atomicity, no visibility guarantees. Use only for statistics counters where ordering does not matter.
✓Acquire: prevents later operations from moving before. Used when loading a flag or lock state.
✓Release: prevents earlier operations from moving after. Used when storing a flag or releasing a lock.
✓Acquire/Release pair synchronizes producer and consumer. Producer release store, consumer acquire load.
✓Sequential consistency (seq_cst): strongest guarantee, all threads agree on order. Default in Java volatile, slowest option.
📌 Examples
1C++ flag pattern: flag.store(true, memory_order_release); ... if (flag.load(memory_order_acquire)) { // data is ready }
2Relaxed counter: counter.fetch_add(1, memory_order_relaxed); // Fine for statistics, not for coordination.