前篇部落格【死磕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)!

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于结构化数据处理开源库SPL的相关问题,下面就一起来看一下java下理想的结构化数据处理类库,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于PriorityQueue优先级队列的相关知识,Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于java锁的相关问题,包括了独占锁、悲观锁、乐观锁、共享锁等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于多线程的相关问题,包括了线程安装、线程加锁与线程不安全的原因、线程安全的标准类等等内容,希望对大家有帮助。

本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于关键字中this和super的相关问题,以及他们的一些区别,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于枚举的相关问题,包括了枚举的基本操作、集合类对枚举的支持等等内容,下面一起来看一下,希望对大家有帮助。

封装是一种信息隐藏技术,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法;封装可以被认为是一个保护屏障,防止指定类的代码和数据被外部类定义的代码随机访问。封装可以通过关键字private,protected和public实现。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于设计模式的相关问题,主要将装饰器模式的相关内容,指在不改变现有对象结构的情况下,动态地给该对象增加一些职责的模式,希望对大家有帮助。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

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

SublimeText3 Linux新版
SublimeText3 Linux最新版

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具