ReviseAlgo Logo

Concurrency

Memory Ordering

Understand the C++ memory model, instruction reordering, and atomic synchronization modes.

Interview: Compiler/CPU instruction reordering, sequential consistency costs, and acquire-release synchronization semantics.

Last Updated: June 13, 2026 9 min read

To optimize performance, compilers and CPUs reorder memory operations. In multi-threaded applications, you specify Memory Ordering on atomic operations to ensure threads see writes in the correct order.

Sequential Consistency

memory_order_seq_cst. The default mode. Guarantees a single global order for all atomic operations across all threads.

Acquire-Release

acquire / release. Synchronizes data write-read paths between specific threads.

Relaxed

memory_order_relaxed. Guarantees atomicity of the operation, but enforces no ordering constraint on surrounding memory operations.

Acquire-Release Semantics

Acquire-release ordering is a common way to synchronize threads without using full sequential consistency:

  • Release: When a thread stores a value using memory_order_release, all its previous writes (even non-atomic ones) become visible to other threads.
  • Acquire: When a thread reads that value using memory_order_acquire, it is guaranteed to see all memory writes that occurred before the release store.

Code Walkthrough

Implementing a thread-safe message pass using acquire-release memory ordering.

#include <iostream>
#include <atomic>
#include <thread>
#include <string>

std::atomic<bool> g_ready(false); std::string g_data;

void producer() { g_data = "Secret message payload"; // Non-atomic write // Release: ensures data write is visible to acquire reads g_ready.store(true, std::memory_order_release); }

void consumer() { // Acquire: blocks until ready is true and synchronizes previous writes while (!g_ready.load(std::memory_order_acquire)) { // Spin lock } std::cout << "Consumer read: " << g_data << std::endl; }

int main() { std::thread t1(consumer); std::thread t2(producer); t1.join(); t2.join(); return 0; }

Interview-Relevant Information

Q: Why does the compiler reorder instructions?
Answer: The compiler reorders instructions to optimize pipeline execution, combine adjacent memory accesses, and hide memory access latency. However, it assumes a single-threaded execution model, which can lead to bugs in multi-threaded code unless you specify ordering constraints using atomics.

Q: What is the performance cost of memory_order_seq_cst?
Answer: Sequential consistency forces the CPU to use hardware memory barriers to coordinate memory caches across cores. This halts pipeline execution and stalls CPU cores, making it the slowest memory ordering mode.

Quick Checklist

Do you know when to use relaxed vs. sequential consistency ordering? Do you use acquire-release to synchronize data? If yes, your lock-free code is optimized.

Use Cases

Optimizing performance-critical lock-free ring buffers in real-time audio systems.

Writing lightweight atomic statistics counters where update order does not affect program logic.

Common Mistakes

Assuming relaxed ordering guarantees visibility of surrounding memory modifications (it only guarantees atomicity of the target variable).

Using sequential consistency everywhere, introducing unnecessary performance overhead.