int x=0; // thread-a
int y=x; // thread-b
int x=5;
int y=8;
int z=x+y;
關於上面的**,存在這樣關係:x和z之間存在資料依賴關係,同時y和z之間也存在資料依賴關係。為了得到正確的結果,執行指令序列時,z不能重排序到x和y的前面。但是x和y之間並沒有資料依賴關係,根據我們上面講的,沒有資料依賴關係處理器和編譯器會對指令進行重排序,所以x和y的執行順序會被重新調整下面兩種情況:
y-》x-》z 結果為:13
x-》y-》z 結果為:13
上面的**如果是多執行緒的情況下進行重排序,會影響程式的執行結果,所以才引發出多執行緒高併發下資料不一致一系列問題。這裡有引出了另乙個概念記憶體屏障。
記憶體屏障
記憶體屏障的出現主要是禁止處理器的重排序,並強制把寫緩衝區中的髒資料寫回主記憶體,從而讓程式按我們預想的流程去執行。記憶體屏障有些材料又叫記憶體柵欄,是乙個cpu指令,volatile就是基於記憶體屏障實現的。
記憶體屏障分load barrier(讀屏障)和store barrier(寫屏障)兩種。
對於讀屏障,在指令前插入load barrier,可以讓快取記憶體中的資料失效,強制從主記憶體載入資料;
對於寫屏障,在指令後插入store barrier,可以讓寫入快取中的最新資料更新寫入主記憶體,讓其他執行緒可見。
對於load和store實際又分為以下四種
loadload屏障
序列: load1;loadload;load2
說明: 確保load1所要讀入的資料能夠在被load2和後續的load指令訪問前讀入。
storestore屏障
序列: store1;storestore;store2
說明: 確保store1的資料在store2以及後續store指令操作相關資料之前對其它處理器可見。
loadstore屏障
序列: load1;loadstore;store2
說明: 確保load1的資料在store2和後續store指令被重新整理之前讀取。
storeload屏障
序列: store1;storeload;load2
說明: 確保store1的資料在被load2和後續的load指令讀取之前對其他處理器可見。
>>>>閱讀全文
java記憶體模型
一 原子性 原子性是指乙個操作是不可中斷的,即使是多個執行緒一起執行的時候,乙個操作的開始,就不會被其他執行緒干擾 那麼有人會想到 i 是原子操作嗎?答案肯定不是。因為i 至少包含兩個操作,讀 從記憶體中讀出來 和行為 加上去 還有可能把加完後的資料在方法到i裡面去,出來也是1,這兩個執行緒同時進行...
Java記憶體模型
1.首先,執行緒a把本地記憶體a中更新過的共享變數重新整理到主記憶體中去。2.然後,執行緒b到主記憶體中去讀取執行緒a之前已更新過的共享變數。1.共享物件對各個執行緒的可見性 2.共享物件的競爭現象 指令級並行的重排序 如果不存l在資料依賴性,處理器可以改變語句對應機器指令的執行順序。記憶體系統的重...
java記憶體模型
執行緒之間的共享變數儲存在主記憶體中,每個執行緒對應乙個私有的本地變數為共享變數的副本 指令重排序 資料依賴性 as if serial 乙個執行緒的操作必須按照程式的順序來執行 每個操作必須原子性和立刻對所有執行緒可見 允許把乙個64位的double和long型別的寫操作拆分成兩個32位操作來執行...