Course contentsShow
← Rust
Lesson 1765 of 1,91015. Performance and Architectural EngineeringFree lesson

Concurrency and Memory Consistency Models

Navigate hardware-level memory models to ensure correctness without over-synchronizing.

In this lesson, you will learn how to navigate the gap between your code’s logic and the hardware’s reality by selecting the right memory consistency model to avoid over-synchronization.

The Illusion of Sequential Consistency

When we write concurrent Rust, we often assume Sequential Consistency (SC)—the idea that all threads see operations in the same order they appear in the source code. While intuitive, SC is expensive. Modern CPUs use store buffers, speculative execution, and out-of-order execution to hide latency. If you enforce SC globally, you force the CPU to stall or flush these buffers, which kills performance.

Relaxing the Hardware Contract

Rust’s std::sync::atomic provides the tools to tune this contract. Instead of defaulting to Ordering::SeqCst (which imposes a total global order), you can use Acquire and Release semantics to create happens-before relationships.

Consider a shared flag:

// Producer thread
data.store(100, Ordering::Relaxed);
flag.store(true, Ordering::Release); // Ensures data store is visible before flag

// Consumer thread
if flag.load(Ordering::Acquire) {
    // We are guaranteed to see the write to 'data'
    assert_eq!(data.load(Ordering::Relaxed), 100);
}

In this pattern, the Release on the producer "publishes" the preceding memory operations, and the Acquire on the consumer "synchronizes" with that store. Notice that data only needs Relaxed ordering. Because the flag acts as a guard, the hardware is permitted to reorder operations within those bounds, provided the dependency remains consistent.

Engineering Balance

The goal of high-performance architectural engineering is to use the weakest ordering that satisfies your correctness requirements. If you use SeqCst everywhere, you are essentially asking the hardware to pretend it is a single-core machine, which negates the performance gains of your multi-core architecture. By understanding the memory model, you trade off the simplicity of global ordering for the raw throughput of architecture-aware concurrency.

Key Takeaway: Optimize performance by using the weakest memory ordering necessary to establish the required happens-before relationships, avoiding the heavy performance penalty of global sequential consistency.