Repository navigation
memory model
The C++ Memory Model (introduced in C++11) is a formal set of rules that defines how different threads interact through shared memory. It provides a standardized "contract" between the programmer, the compiler, and the hardware, ensuring that multithreaded code behaves predictably across different platforms.
Before C++11, the language lacked a built-in understanding of threads. Compilers and CPUs often optimize performance by [reordering instructions] or [caching values] in ways that are invisible in a single-threaded environment but can cause ["data races"] and unpredictable results in [multithreaded code].
The memory model specifies:
- [Visibility]: When a write to a variable by one thread becomes visible to another.
- [Ordering]: Which instructions can be reordered and which must stay in sequence.
The memory model is built on three main pillars:
-
[Atomic Operations] (std::atomic)Atomic operations are indivisible—no thread can see the operation in a "half-finished" state. They are the building blocks of thread-safe communication without using heavy locks like mutexes. Use the std::atomic documentation to explore available types.
-
[Memory Ordering Constraints] You can specify how strictly the compiler and CPU must order memory accesses. The most common types available via std::memory_order include:
-
Sequential Consistency (memory_order_seq_cst): The strictest and default mode. It guarantees that all threads see memory operations in the exact same global order.
-
Acquire-Release (memory_order_acquire, memory_order_release): A middle ground where a thread "releasing" a variable synchronizes specifically with a thread "acquiring" it.
-
Relaxed (memory_order_relaxed): No synchronization or ordering; only guarantees the operation itself is atomic.
-
The ["Happens-Before"] Relationship
This is the mathematical foundation of the model. If operation (A) "happens-before" operation (B), then (A) is guaranteed to be visible to (B). If two threads access the same memory and neither access "happens-before" the other (and at least one is a write), a Data Race occurs, which results in Undefined Behavior.
- Portability: Code written following the C++ memory model will work correctly on both "strong" hardware like x86 and "weak" hardware like ARM.
- Performance: By allowing "relaxed" or "acquire-release" ordering, experts can write high-performance, lock-free algorithms that avoid the overhead of full sequential consistency.
- Tooling Support: Tools like CppMem allow developers to mathematically verify if their concurrent code is race-free.
My footer
My side bar