記憶體模型與原子操作

memory_order 列舉(the memory_order enumeration)

/ memory_order -> MEM-ree OR-der /

當你做一個原子操作時,你其實還在做第二個、獨立的選擇:這個操作必須把周遭多少記憶體流量釘在原地?memory_order 列舉就是那份簡短的答案選單。它讓你只為自己真正需要的排序強度付費,因為更強的排序在中央處理器上可能消耗實實在在的週期與屏障。

六個值由強到弱依序是:memory_order_seq_cst(預設——所有人都同意的單一全域順序)、memory_order_acq_rel(給讀改寫操作用:載入側 acquire、儲存側 release)、memory_order_acquire(一次載入,之後的任何讀/寫都不得上浮越過它)、memory_order_release(一次儲存,之前的任何讀/寫都不得下沉越過它)、memory_order_consume(acquire 的一個較弱、且不被鼓勵的近親,只跟隨資料相依)、以及 memory_order_relaxed(原子,但除了該位置自身的修改順序外完全沒有任何排序保證)。在 Rust,對應的列舉是 std::sync::atomic::Ordering,其變體有 SeqCst、AcqRel、Acquire、Release 與 Relaxed(Rust 刻意省略 Consume)。

實務建議誠實而直白:一開始到處都用 seq_cst。它最容易推理,且預設就正確。只有在你量測出真正的瓶頸、並能基於 happens-before 關係論證較弱順序仍然正確之後,才去削弱排序。大多數 relaxed/acquire/release 的臭蟲,都源自程式設計師伸手去拿自己其實不需要的速度,卻打破了一個他們沒意識到自己依賴的不變式。

atomic_store_explicit(&p, ptr, memory_order_release); /* 寫端 */ T *q = atomic_load_explicit(&p, memory_order_acquire); /* 讀端 */ /* 這對 release/acquire 讓寫端在儲存之前做的一切,對讀端在載入之後可見 */

release/acquire 配對是主力:比 seq_cst 便宜,又強到足以安全地在兩個執行緒間遞交資料。

排序標籤只有在跨執行緒「成對」時才有意義——一個孤零零、沒有對應 acquire 的 release(或反之)什麼也不同步;這些標籤描述的是一種關係,而非單一存取的性質。

又称
std::memory_orderOrdering (Rust)記憶體順序列舉