一:保證記憶體的可見性
二:對任意單個volatile變數的讀/寫具有原子性,但類似於volatile++這種復合操作不具有原子性
三:禁止指令的重排序
解析:一:對於使用volatile關鍵字的共享變數,會強制將修改後的值立即寫入主記憶體,並會使得其他處理器裡面的快取行失效(嗅探機制,快取一致性協議),所以其他執行緒會重新從主記憶體中獲取對應的新值,所以可見性是通過主記憶體來實現的。
二:可以理解volatile具有一定的原子性,但不是全部:
private volatile boolean stop = false;
//執行緒一:此時對於stop的讀/寫 是具有原子性的:stop沒有用volatile修飾的話,執行緒一是可有能造成死迴圈的。修飾後,由於volatile的可見性,當stop被修改後,執行緒一會立即獲取到最新的stop值,從而暫停。while (!stop)
//執行緒二:
stop = true;
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屏障 在...