循序一致性(sequential consistency)
循序一致性(sequential consistency)是你能盼望一台平行機器去做的最直覺的事——幾乎每個人初次寫多執行緒程式時,都不自覺地假設它。想像把所有核心的記憶體操作一次一個地,餵過一道共享的旋轉門進入記憶體。每個核心自己的操作按它發出的順序通過,但那道旋轉門可以隨意地把不同核心交錯起來。結果是某個尊重每個核心程式順序的單一全域順序。若一台機器的行為彷彿真有這麼一道旋轉門,它就是循序一致的。
說精確一點(Lamport 的定義):任何一次執行的結果,都與「所有核心的所有操作以某個單一循序順序執行」相同,而且每個個別核心的操作,在那個序列中出現的順序,正是它程式所指定的順序。於是有兩個條件:存在一個大家都同意的單一全序,而且在那個順序裡每個核心的操作保持其程式順序。不允許讓任何一個核心自己的載入與儲存彼此之間的重排被看見。這是衡量較弱模型的黃金標準——也是讓並行推理變得可行的心智模型。
誠實的現實是:幾乎沒有任何高效能硬體是循序一致的,因為強制它就禁掉了那些讓核心變快的優化:儲存緩衝區、寫入重排、激進的亂序記憶體都必須被勒住或變得隱形。所以真實處理器提供較弱、放鬆的模型,只讓程式設計師在需要之處靠插入記憶體屏障來找回類似 SC 的行為。因此循序一致性最好被理解為:你用來推理的理想、以及你透過同步去建構的契約——而不是機器在你程式碼之下免費給你的預設行為。
兩個核心,所有變數從 0 開始。核心 A:x = 1;印出 y。核心 B:y = 1;印出 x。在循序一致性下,兩者都印出 0 的情況是不可能的——某個全序必定先跑一個賦值,所以至少有一個印出的值是 1。在真實的放鬆硬體上,兩者都印出 0 真的會發生,第一次見到的人都會嚇一跳。
循序一致性排除了「兩者都印出 0」的結果;放鬆的真實硬體卻允許它,這就是屏障存在的原因。
循序一致性是幾乎每個人都假設的直覺模型,但真實的高效能 CPU 不會免費提供它——它們用放鬆的模型,需要明確的屏障(或定序正確的原子操作)才能找回你預期的順序。