consume 順序(consume ordering)
/ consume -> kuhn-SOOM /
consume 順序是一個聰明的構想,卻沒能在真實編譯器的衝擊下存活。它是 acquire 較弱、較便宜的近親:它不對載入之後的「一切」排序,而只承諾對那些真正「相依」於所載入之值的操作排序——也就是順著你剛讀到的指標走下去才會碰到的那些。在 ARM、POWER 這類弱序硬體上,晶片本來就免費強制這種「資料相依」排序,所以 consume 本意是恰好捕捉這一點、並避開昂貴的屏障。
這個構想是:若你做 p = atomic_load(&head, memory_order_consume) 然後讀 p->next,對 p->next 的讀取「攜帶相依」於那次載入,因此被排在它之後——但一個不相關的全域讀取則「不會」,這正是它比 acquire 便宜之處。它建立的是一條更狹窄、只沿著資料相依鏈流動的 happens-before 邊,非常適合走訪由某個 release 儲存所發布的無鎖鏈結結構。
為何不被鼓勵?要追蹤相依鏈穿越任意原始碼(跨函式呼叫、穿過那個熱愛靠值推測或把相依轉成控制分支來打斷相依的最佳化器)被證明根本行不通。每一個主要編譯器乾脆把 memory_order_consume「當成」memory_order_acquire 實作——悄悄把它加強——於是你付了 acquire 的代價,卻沒換到任何可移植的好處。C++ 委員會已正式不鼓勵使用它,等待重新設計;Rust 則從未提供它。實務建議:用 acquire;別再寫新的 consume 程式。
Node *p = atomic_load_explicit(&head, memory_order_consume); int v = p->value; /* 對 p->value 的讀取攜帶相依於 p */ /* 今天每一個真實編譯器都把這個 consume 編成 acquire */
相依排序的走訪——理論上優雅,實務上不過是換了名字的 acquire。
別再用 memory_order_consume 寫新程式:它已被正式不鼓勵、普遍被實作成 acquire,且其相依規則細到連專家都會搞錯——改用 acquire 就好。