volatile的記憶體語義

2021-10-10 01:56:39 字數 1357 閱讀 1423

一:保證記憶體的可見性

二:對任意單個volatile變數的讀/寫具有原子性,但類似於volatile++這種復合操作不具有原子性

三:禁止指令的重排序

解析:一:對於使用volatile關鍵字的共享變數,會強制將修改後的值立即寫入主記憶體,並會使得其他處理器裡面的快取行失效(嗅探機制,快取一致性協議),所以其他執行緒會重新從主記憶體中獲取對應的新值,所以可見性是通過主記憶體來實現的。

二:可以理解volatile具有一定的原子性,但不是全部:

private volatile boolean stop = false;
//執行緒一:

while (!stop)

//執行緒二:

stop = true;

此時對於stop的讀/寫 是具有原子性的:stop沒有用volatile修飾的話,執行緒一是可有能造成死迴圈的。修飾後,由於volatile的可見性,當stop被修改後,執行緒一會立即獲取到最新的stop值,從而暫停。

volatile++這種復合操作不具有原子性:

復合操作其實執行了三步操作了:1.從主記憶體讀取值x=0;     2.執行x++;    3.再把x=1刷回主記憶體

a,b倆個執行緒同時操作被volatile修飾的共享變數x時,都執行到第一步,同時讀取了x的值為0。

此時a變數率先執行完到第2步第3步,x的值為1刷回到主記憶體了。

但b執行緒已經執行到第2步了,即使x此時的值為1,b執行緒執行第2步的操作時是x=0+1,而不是x=x+1,所以最後結果還是1

三:重排序(記憶體屏障)

在每個volatile寫操作前插入乙個storestore屏障,操作後插入storeload屏障

在每個volatile讀操作後插入loadload屏障和loadstore屏障

storestore屏障保證volatile寫之前,前面的所有普通操作都已經對任意處理器可見,即將上面的都已經重新整理到主記憶體

storeload屏障是為了避免volatile寫操作與後面可能出現的volatile讀/寫操作重排序

編譯器對記憶體屏障還進行優化:

記憶體屏障的插入還可以根據具體的處理器記憶體模型繼續優化

volatile記憶體語義

1 可見性 不管是volatile讀還是volatile寫,都會重新訪問主記憶體取最新的值 2 有序性 防止重排序 volatile寫前 storestore屏障 首先先把前面的普通寫操作執行到主記憶體,在執行volatile寫操作執行到記憶體 保證前面普通寫操作和volatile寫操作不重排,前面...

volatile的記憶體語義

volatile的應用與底層原理詳見 volatile的應用與底層原理 class volatilefeature ample public void getandincrement public long get 假設有多個執行緒分別呼叫上面程式的3個方法,這個程式在語義上和下面程式等價。clas...

volatile記憶體語義的實現

為了實現volatile的記憶體語義,編譯器在生成位元組碼時,會把指令序列中插入記憶體屏障來禁止特定型別的處理器重排序。下面是基於保守策略的jmm記憶體屏障插入策略 在每個volatile寫操作前面插入乙個storestore屏障 在每個volatile寫操作後面插進入乙個storeload屏障 在...