天天看點

記憶體屏障一、重排序 二、記憶體屏障三、記憶體屏障的種類

編譯器和處理器必須同時遵守重排規則。多核處理器需使用記憶體屏障指令來確定一緻性。即使編譯器優化掉了一個字段通路(因為一個讀入的值未被使用),需要産生記憶體屏障,就像這個通路仍然需要保護。(可參考下面的優化掉記憶體屏障的章節)。

記憶體屏障指令僅直接控制CPU與其緩存之間,與垃圾回收機制中“寫屏障(write barriers)”無關。

一、重排序

編譯器或者CPU的代碼的結構重排排序,達到最佳效果。

(1)編譯器重排

CPU隻讀一次的x和y值。不需反複讀取寄存器來交替x和y值。

(2)處理器重排

寫緩存區沒有及時重新整理,使得處理器執行的讀寫操作與記憶體上順序不一緻。

處理器A讀b=0,處理器B讀a=0。A1寫a=1先寫到處理器A的寫緩存區中,此時記憶體中a=0。如果這時處理器B從記憶體中讀a,讀到的将是0。

可能會出現x,y都是0。

二、記憶體屏障

為了解決上述問題,處理器提供記憶體屏障指令(Memory Barrier):

寫記憶體屏障(Store Memory Barrier):處理器将存儲緩存值寫回主存(阻塞方式)。

讀記憶體屏障(Load Memory Barrier):處理器,處理失效隊列(阻塞方式)。

保證兩個操作之間資料的可見性。

volatile讀前插讀屏障,寫後加寫屏障,避免CPU重排導緻的問題,實作多線程之間資料的可見性。

三、記憶體屏障的種類

StoreLoad開銷最大。萬能屏障,兼具其它三種記憶體屏障功能。執行時,處理器通常要把寫緩沖區中的資料全部重新整理的記憶體中

對于處理器來說,記憶體屏障會導緻cpu緩存的重新整理,重新整理時,會遵循緩存一緻性協定。

lock:

解鎖時,jvm會強制重新整理cpu緩存,導緻目前線程更改,對其他線程可見。

volatile:

(1)對于寫操作:對變量更改完之後,要立刻寫回到主存中。

(2)對于讀操作:對變量讀取的時候,要從主存中讀,而不是緩存。

final:即時編譯器在final寫操作後,會插入記憶體屏障,來禁止重排序,保證可見性