Key Insight
Memory models are complex. Here are practical guidelines that keep you safe without requiring PhD-level understanding.
Rule 1: Use High-Level Primitives
Mutexes, condition variables, and concurrent data structures handle memory ordering for you. Do not roll your own unless you have to.
Rule 2: Default to Sequential Consistency
When using atomics, use the default (seq_cst in C++, volatile in Java). It is slower but correct. Optimize later if needed.
Safe Patterns
Rule 3: Beware of Benign Data Races
In C/C++, any data race is undefined behavior - even benign ones. Java is more forgiving but still has surprising semantics.
Rule 4: Test on Weak Architectures
x86 has strong ordering that hides bugs. ARM and POWER are weaker. A bug that never appears on x86 might crash on ARM. Test on actual target hardware.
Rule 5: Use Tools
ThreadSanitizer catches data races. Formal verification tools (CDSChecker, Relacy) can exhaustively test memory model compliance.
Bottom Line: Memory models are a minefield. Stay on the safe paths unless you truly need the performance and have the expertise.
✓Default to sequential consistency. It matches programmer intuition and is correct. Optimize only after profiling.
✓Locks provide implicit memory ordering. All writes before unlock are visible after lock. Simplest to reason about.
✓Atomic read modify write (CAS, getAndIncrement) is safer than separate load/store. Self contained operations are easier.
✓x86 has strong memory model, ARM is weaker. Code may work on x86 but break on ARM. Test on multiple architectures.
✓Use ThreadSanitizer. It detects many memory ordering bugs by simulating weak memory models.