記憶體模型與原子操作

儲存緩衝區(store buffer)

/ store buffer -> stor BUH-fer /

當一個中央處理器核心寫入記憶體時,它通常不會等那次寫入抵達快取、更別說主記憶體——那會慢得令人痛苦。它反而把寫入丟進一個小而快、每核心各自的佇列,叫做儲存緩衝區,然後核心就衝去執行下一條指令。那個儲存稍後才在背景從緩衝區排空進快取。把它想成一個寄件匣:你把信丟進去就走人,它終究會被寄出。

這一塊硬體正是你讀到的大多數令人意外的記憶體重排背後的具體「原因」。因為一個儲存在全域可見之前先待在緩衝區裡,一個對「不同」位址、較年輕的載入可以先完成——這就是連 x86 TSO 也允許的著名 store-to-load 重排。核心也能偷看自己緩衝區裡尚未排空的儲存(store-to-load 轉送),所以它立刻看得到自己的寫入,即使其他核心還看不到。把那個緩衝區排空,你就還原了順序;一道完整的記憶體屏障、或一個 seq_cst 儲存,本質上強迫緩衝區在繼續之前清空,這正是那些操作較貴的原因。

把它扣回來:儲存緩衝區正是 release/acquire 不會自動發生、以及屏障之所以存在的原因。它也是經典儲存緩衝區試金石測試的核心——兩個執行緒各自先儲存再載入對方的變數,可能「兩者都」讀到陳舊值,因為載入執行時每個儲存都還停在自己的緩衝區裡。理解儲存緩衝區,能把記憶體模型從一張任意規則的清單,變成一幅硬體實際在做什麼的圖像。

核心 A:store x=1(待在 A 的緩衝區裡);接著 load y -> 讀到 0(y 尚未被儲存) 核心 B:store y=1(待在 B 的緩衝區裡);接著 load x -> 讀到 0(x 還在 A 的緩衝區裡) 兩邊都看到 0——這不是臭蟲,只是兩個儲存緩衝區都還沒排空。

活生生的儲存緩衝區效應:每個核心待處理的寫入,在緩衝區排空前對另一核心都是看不見的。

儲存緩衝區對單執行緒程式與快取一致性都是看不見的(一致性仍讓每個位址的寫入保持有序);它是一種「consistency」效應,而一道屏障的成本,大部分「就是」排空它的成本。

又称
write buffer寫入緩衝區