Java volatile關鍵字解析
在多執行緒併發程式設計中synchronized和volatile都扮演者重要角色。volatile是輕量級的synchronized,它在多處理器開發中保證了共享變數的“可見性”。
一、volatile的特性
記憶體可見性:執行緒A對一個volatile變數的修改,對於其他執行緒是可見的,即執行緒獲取volatile變數的值都是最新的。
二、實現原理相關說明
記憶體屏障(memory barriers)是一組處理器指令,用於實現對記憶體操作的順序限制。
緩衝行(cache line)CPU快取記憶體中可以分配的最小儲存單位。處理器填寫快取行時,會載入整個快取行。
原子操作(atomic operations)不可中斷的一個或一系列操作。
三、如何保證記憶體可見性
在X86處理器下通過工具獲取JIT編譯器生成的彙編指令來檢視對volatile寫操作時的情況。
Java程式碼
instance = new Singleton();//instance是volatile變數
轉變為彙編程式碼
0x01a3deld:movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);
有volatile變數修飾的共享變數進行寫操作時會多一行彙編程式碼,其中有lock關鍵詞,Lock字首指令在多核處理器下會引發兩件事情:
- 將當前處理器快取行的資料寫回到系統記憶體。
- 這個寫回操作會使在其他CPU裡快取了該記憶體地址的資料無效。
為了提高處理速度,處理器不直接和記憶體進行通訊,而是先將系統記憶體的資料讀到內部快取後再進行操作,但是操作完不知道何時寫到記憶體中。
如果對宣告瞭volatile變數進行寫操作,JVM就會向處理器傳送一個Lock字首指令,將這個變數所在的快取行的資料寫回到系統記憶體。但其他處理器快取的值還是舊的,所有在多處理器環境下,為保證各個處理器的快取是一致的,就回實現快取一致性協議,每個處理器通過嗅探在匯流排上傳播的資料來檢查自己快取的值是不是過期了,當處理器發現自己快取行對應的記憶體地址被修改,就會將該快取行設定為無效狀態,當處理器對這個資料進行操作時就會重新從記憶體中讀取資料到快取中。
四、volatile實現原則
1.Lock字首指令會引起處理器快取寫回到記憶體。
2.一個處理器的快取寫回到記憶體會導致其他處理器的快取無效。
五、volatile的使用場景
通過關鍵字sychronize可以防止多個執行緒進入同一段程式碼,在某些特定場景中,volatile相當於一個輕量級的sychronize,因為不會引起執行緒的上下文切換,但是使用volatile必須滿足兩個條件:
- 對變數的寫操作不依賴當前值,如多執行緒下執行a++,是無法通過volatile保證結果準確性的;
- 該變數沒有包含在具有其它變數的不變式中,這句話有點拗口,看程式碼比較直觀。
在專案中經常會用到volatile關鍵字的兩個場景:
1、狀態標記量
在高併發環境中,通過一個boolean型別的變數 flag,控制程式碼是否走其他邏輯。
public class Handler {
private volatile flag;
public void setFlag(boolean flag) {
this.flag = falag;
}
public void run() {
if (flag) {
//其他邏輯
} else {
//正常邏輯
}
}
}
使用者的請求執行緒執行run方法,如果需要開啟其他活動,可以通過後臺設定,具體實現可以傳送一個請求,呼叫其他方法並設定flag為true,由於flag是volatile修飾的,所以一經修改,其他執行緒都可以拿到flag的最新值,使用者請求就可以執行其他邏輯了。
2.雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)
單例模式的一種實現方式,如果沒有volatile關鍵字,會出現bug。
- volatile關鍵字可以保證jvm執行的一定的"有序性",在指令1和指令2執行完之前,指定3一定不會被執行。(禁止重排序)
- 保證了volatile變數被修改後立刻重新整理會駐記憶體中。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
參考資料:
-《Java併發程式設計的藝術》 方騰飛 魏鵬 程曉明 著
- https://www.jianshu.com/p/195ae7c77afe 佔小狼
相關文章
- Java併發—— 關鍵字volatile解析Java
- volatile關鍵字解析
- 深入解析volatile關鍵字
- volatile關鍵字解析~高階java必問Java
- Java volatile關鍵字作用Java
- Java併發程式設計:volatile關鍵字解析Java程式設計
- Java之併發程式設計:volatile關鍵字解析Java程式設計
- 從根源上解析 Java volatile 關鍵字的實現Java
- Java關鍵字volatile的理解Java
- Volatile關鍵字
- java併發之volatile關鍵字Java
- Java記憶體模型——volatile關鍵字Java記憶體模型
- 深入瞭解 Java 的 volatile 關鍵字Java
- Java併發程式設計volatile關鍵字Java程式設計
- 深入理解Java中的volatile關鍵字Java
- Java多執行緒(二)volatile關鍵字Java執行緒
- java併發程式設計——volatile關鍵字Java程式設計
- java記憶體模型及volatile關鍵字Java記憶體模型
- java併發程式設計:volatile關鍵字Java程式設計
- Java面試題集錦(1):volatile關鍵字Java面試題
- 深入彙編指令理解Java關鍵字volatileJava
- java多執行緒4:volatile關鍵字Java執行緒
- Java記憶體模型與volatile關鍵字Java記憶體模型
- 快速理解 volatile 關鍵字
- Java面試官最愛問的volatile關鍵字Java面試
- Java面試題:請談談Java中的volatile關鍵字?Java面試題
- 兩張圖理解volatile關鍵字
- volatile關鍵字的作用、原理
- Java併發——關鍵字synchronized解析Javasynchronized
- Java中的static關鍵字解析Java
- Java 面試官最喜歡問的關鍵字 volatileJava面試
- Java多執行緒學習(三)volatile關鍵字Java執行緒
- 就是要你懂Java中volatile關鍵字實現原理Java
- 一個具體的例子學習Java volatile關鍵字Java
- Java併發專題(三)深入理解volatile關鍵字Java
- 全面理解Java記憶體模型(JMM)及volatile關鍵字Java記憶體模型
- 再識Java併發程式設計關鍵字之volatileJava程式設計
- Java執行緒面試題(03) Java中的volatile如何工作? Java中的volatile關鍵字示例Java執行緒面試題