前篇部落格【死磕Java並發】—–深入分析volatile的實作原理中已經闡述了volatile的特性了:
volatile可見性;對一個volatile的讀,總是可以看到這個變數最終的寫;
volatile原子性;volatile對單一讀/寫具有原子性(32位元Long、Double),但是複合操作除外,例如i++;
JVM底層採用「記憶體屏障」來實現volatile語意
下面LZ就透過happens-before原則和volatile的記憶體語意兩個方向介紹volatile。
volatile與happens-before
在這篇部落格【死磕Java並發】—–Java記憶體模型之happend-before中LZ闡述了happens-before是用來判斷是否存數據競爭、執行緒是否安全的主要依據,它保證了多執行緒環境下的可見性。下面我們就那個經典的例子來分析volatile變數的讀寫建立的happens-before關係。
public class VolatileTest { int i = 0; volatile boolean flag = false; //Thread A public void write(){ i = 2; //1 flag = true; //2 } //Thread B public void read(){ if(flag){ //3 System.out.println("---i = " + i); //4 } } }
依據happens-before原則,就上面程序得到如下關係:
- ##依據happens-before程序順序原則:1 happens-before 2、3 happens-before 4;
- 根據happens-before的volatile原則:2 happens-before 3;
- 根據happens-before的傳遞性:1 happens -before 4
當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數值立即刷新到主記憶體中。所以volatile的寫記憶體語意是直接刷新到主記憶體中,讀的記憶體語意是直接從主記憶體中讀取。當讀取一個volatile變數時,JMM會把該執行緒對應的本地記憶體設定為無效,直接從主記憶體讀取共享變數
那麼volatile的記憶體語意是如何實現的呢?對於一般的變數則會被重新排序,而對於volatile則不能,這樣會影響其記憶體語義,所以為了實作volatile的記憶體語意JMM會限制重排序。其重排序規則如下:
- 如果第一個運算為volatile讀,則不管第二個運算是啥,都不能重新排序。這個操作確保volatile讀之後的操作不會被編譯器重排序到volatile讀之前;
- #當第二個操作為volatile寫是,則不管第一個操作是啥,都不能重排序。這個操作確保volatile寫之前的操作不會被編譯器重排序到volatile寫之後;
- #當第一個操作volatile寫,第二個操作為volatile讀時,不能重新排序。
- 在每一個volatile寫入作業前面插入一個StoreStore屏障
- 在每一個volatile寫入作業後面插入一個StoreLoad屏障
- 在每一個volatile讀取作業後面插入一個LoadLoad屏障
- 在每一個volatile讀取作業後面插入一個LoadStore屏障
public class VolatileTest { int i = 0; volatile boolean flag = false; public void write(){ i = 2; flag = true; } public void read(){ if(flag){ System.out.println("---i = " + i); } } }
public class VolatileBarrierExample { int a = 0; volatile int v1 = 1; volatile int v2 = 2; void readAndWrite(){ int i = v1; //volatile读 int j = v2; //volatile读 a = i + j; //普通读 v1 = i + 1; //volatile写 v2 = j * 2; //volatile写 } }沒有優化的範例圖如下:
1:這個肯定要保留了
2:禁止下面所有的普通寫與上面的volatile讀重排序,但是由於存在第二個volatile讀,那個普通的讀根本無法越過第二個volatile讀。所以可以省略。
3:下面已經不存在普通讀了,可以省略。
4:保留
5:保留
6:下面跟著一個volatile寫,所以可以省略
7:保留
8:保留
所以2、3、6可以省略,其示意圖如下:
以上就是【死磕Java並發】-----Java記憶體模型之分析volatile的內容,更多相關內容請關注PHP中文網(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

記事本++7.3.1
好用且免費的程式碼編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。