Memory Model

mohitmishra786/low-level-dev-skills/skills/low-level-programming/memory-model

作者 mohitmishra786bdc58472fa9f無授權條款253 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫3 個月前更新

C++ and Rust memory model skill for concurrent programming. Use when understanding memory ordering, writing lock-free data structures, using std::atomic or Rust atomics, diagnosing data races, or selecting the correct memory order for atomic operations. Activates on queries about memory ordering, acquire-release, seq_cst, relaxed atomics, happens-before, memory barriers, std::atomic, or Rust atomic ordering.

AI 產生的概覽

引導代理理解 C++ 與 Rust 記憶體模型、記憶體順序、原子操作、柵欄及無鎖模式。

功能
此技能提供 C++ 與 Rust 記憶體模型的指引,涵蓋 relaxed、acquire、release、acq_rel、seq_cst 等記憶體順序、happens-before 關係、原子操作與柵欄。內容包含選擇記憶體順序的決策指引、自旋鎖、引用計數與一次性初始化的程式碼模式,以及常見錯誤與修正對照表。它也指向一份關於記憶體順序規則與 happens-before 的參考檔案。
適用情境
適用於解釋記憶體順序、撰寫無鎖資料結構、使用 std::atomic 或 Rust 原子型別、診斷資料競爭,或為原子操作選擇正確記憶體順序的情境。也適用於關於 acquire-release、seq_cst、relaxed 原子操作、happens-before 與記憶體屏障的問題。
執行需求
不需要指令碼或特殊工具,僅為說明性內容。它引用了一份隨附的 C++ 記憶體順序 Markdown 參考檔案。

Memory Model

Purpose

Guide agents through C++ and Rust memory models: memory orderings, the happens-before relation, atomic operations, fences, and practical patterns for lock-free data structures.

Triggers

  • "What is the C++ memory model?"
  • "What memory order should I use for my atomic operation?"
  • "What is the difference between acquire-release and seq_cst?"
  • "How do I use std::atomic in C++?"
  • "What is acquire/release in Rust atomics?"
  • "How do I implement a lock-free queue?"

Workflow

1. Memory ordering overview

Modern CPUs and compilers reorder operations for performance. The memory model specifies what reorderings are allowed and how synchronisation is achieved.

text
Ordering strength (weakest to strongest):Relaxed < Release/Acquire < AcqRel < SeqCst
Stronger ordering = more synchronization = more correct, but slowerWeaker ordering  = fewer barriers = faster, but needs careful analysis

2. Memory orderings

OrderC++RustWhat it means
Relaxedmemory_order_relaxedOrdering::RelaxedNo ordering guarantee; just atomicity
Consumememory_order_consume(use Acquire)Data dependency ordering
Acquirememory_order_acquireOrdering::AcquireThis load sees all writes before the matching release
Releasememory_order_releaseOrdering::ReleaseAll writes before this store are visible to acquire
AcqRelmemory_order_acq_relOrdering::AcqRelBoth acquire and release on RMW ops
SeqCstmemory_order_seq_cstOrdering::SeqCstTotal order across all seq_cst operations

3. C++ std::atomic

cpp
#include <atomic>#include <thread>
std::atomic<int> counter{0};std::atomic<bool> ready{false};
// Producer threadvoid producer() {    data = 42;                              // (1) write data    ready.store(true, std::memory_order_release);  // (2) signal}
// Consumer threadvoid consumer() {    while (!ready.load(std::memory_order_acquire));  // (3) wait    assert(data == 42);                              // (4) guaranteed to see (1)}

Acquire-release guarantees: if thread A does a release store to X, and thread B does an acquire load that sees A's value, then all writes by A before the release are visible to B after the acquire.

4. Choosing the right ordering

text
Use case?├── Counter (just needs atomicity, order irrelevant)    → Relaxed├── Reference counting (decrement + final check)        → AcqRel (dec), Acquire (load 0 check)├── Publish data from one thread to another             → Release (store), Acquire (load)├── Mutual exclusion / mutex implementation             → AcqRel / SeqCst├── Lock-free queue multiple producers/consumers        → SeqCst (safest to start)└── Sequence number check (simple flag)                 → Release + Acquire

5. Common patterns

cpp
// Pattern 1: Spinlockclass Spinlock {    std::atomic_flag flag = ATOMIC_FLAG_INIT;public:    void lock() {        while (flag.test_and_set(std::memory_order_acquire))            ; // spin    }    void unlock() {        flag.clear(std::memory_order_release);    }};
// Pattern 2: Reference countingclass RefCounted {    std::atomic<int> refcount{1};public:    void addref() {        refcount.fetch_add(1, std::memory_order_relaxed);  // only need atomicity    }    void release() {        if (refcount.fetch_sub(1, std::memory_order_acq_rel) == 1) {            // AcqRel ensures we see all writes from other releasers            delete this;        }    }};
// Pattern 3: One-time initialisationclass LazyInit {    std::atomic<void*> ptr{nullptr};    std::mutex mtx;public:    void* get() {        void* p = ptr.load(std::memory_order_acquire);        if (p == nullptr) {            std::lock_guard lock(mtx);            p = ptr.load(std::memory_order_relaxed);            if (p == nullptr) {                p = create();                ptr.store(p, std::memory_order_release);            }        }        return p;    }};

6. Rust atomics

rust
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};use std::sync::Arc;
// Simple counterlet counter = Arc::new(AtomicUsize::new(0));
// Incrementcounter.fetch_add(1, Ordering::Relaxed);
// Readlet val = counter.load(Ordering::Relaxed);
// Publish/subscribe patternstatic READY: AtomicBool = AtomicBool::new(false);
// Publisher threadunsafe { DATA = 42; }  // Write dataREADY.store(true, Ordering::Release);  // Signal
// Subscriber threadwhile !READY.load(Ordering::Acquire) {}let d = unsafe { DATA };  // Safe: guaranteed to see publisher's write

7. Fences

Fences provide ordering without an atomic operation on a specific variable:

cpp
// C++ fence — equivalent to a global memory barrierstd::atomic_thread_fence(std::memory_order_acquire);  // Acquire fencestd::atomic_thread_fence(std::memory_order_release);  // Release fence
// Typical use: multiple atomic writes then one fencerelaxed_atomic_a.store(1, std::memory_order_relaxed);relaxed_atomic_b.store(2, std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_release);  // barrier for all abovesentinel.store(true, std::memory_order_relaxed);

8. Common mistakes

MistakeFix
Using Relaxed for publish/subscribeUse Release on store, Acquire on load
Using SeqCst everywhereProfile first; use weakest correct ordering
Forgetting that non-atomic loads are not atomicAll shared mutable data needs atomic or mutex
Using volatile for thread safety in C++volatile is not a memory ordering tool; use atomic
Assuming sequential consistency without SeqCstEach platform has different default consistency

For memory ordering rules and happens-before reference, see references/cpp-memory-ordering.md [blocked].

Related skills

  • Use skills/runtimes/sanitizers — TSan detects data races involving non-atomic accesses
  • Use skills/rust/rust-sanitizers-miri for detecting Rust memory ordering violations with Miri
  • Use skills/low-level-programming/assembly-x86 to understand generated fence instructions
  • Use skills/debuggers/gdb for debugging concurrent programs with thread inspection

來源與署名

來源:mohitmishra786/low-level-dev-skills位於skills/low-level-programming/memory-model提交bdc5847

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架