什么是Java内存模型中的happens-before
Java內(nèi)存模型JMM
Java內(nèi)存模型(即Java Memory Model , 簡稱JMM),本身是一種抽象的概念,并不真實(shí)存在,它描述的是一組規(guī)則或規(guī)范,通過這組規(guī)范定義了程序個(gè)各個(gè)變量(包括實(shí)例字段,靜態(tài)字段和構(gòu)成數(shù)組對(duì)象的元素)的訪問方式
?
由于JVM運(yùn)行時(shí)程序的實(shí)體是線程,而每個(gè)線程創(chuàng)建時(shí),而JVM都會(huì)為其創(chuàng)建一個(gè)工作內(nèi)存,有一些地方叫做棧空間,用于存儲(chǔ)線程私有的數(shù)據(jù),而Java內(nèi)存模型中規(guī)定所有的變量都保存在主內(nèi)存中,主內(nèi)存是共享內(nèi)存區(qū)域,所以線程都可以訪問。但線程對(duì)變量的操作,則讀取和賦值等,必須在工作內(nèi)存中進(jìn)行。首先從主內(nèi)存中拷貝變量到工作內(nèi)存中,然后對(duì)變量進(jìn)行操作,操作完成后,再將變量寫回到主內(nèi)存中。注意:線程是不能直接操作主內(nèi)存的變量,工作內(nèi)存中就存在主內(nèi)存變量的副本。因此每個(gè)線程都不能互相訪問對(duì)方的工作內(nèi)存,所以線程之間的通信必須通過主內(nèi)存去進(jìn)行通信。
?
JMM中的住內(nèi)存和工作內(nèi)存
JVM中的主內(nèi)存
1、存儲(chǔ)Java實(shí)例對(duì)象
2、包括成員變量、類信息、常量、靜態(tài)變量等
3、屬于數(shù)據(jù)共享的區(qū)域,多線程并發(fā)操作時(shí)會(huì)引發(fā)線程安全問題
JVM中的工作內(nèi)存
1、存儲(chǔ)當(dāng)前方法的所有本地變量信息,本地變量對(duì)其他線程不可見
2、字節(jié)碼行號(hào)指示器,Native方法信息
3、屬于線程私有數(shù)據(jù)區(qū)域,不存線程安全問題
?
JMM與Java內(nèi)存區(qū)域劃分是不同的概念層
1、JMM描述的是一組規(guī)則,圍繞原子性,有序性,可見性展開
2、相似點(diǎn):存在共享區(qū)域和私有區(qū)域
?
主內(nèi)存與工作內(nèi)存的數(shù)據(jù)存儲(chǔ)類型以及操作方式歸納
1、方法里的基本數(shù)據(jù)類型本地變量將直接存儲(chǔ)在工作內(nèi)存的棧幀結(jié)構(gòu)中
2、引用類型的本地變量:引用存儲(chǔ)在工作內(nèi)存中,實(shí)例存儲(chǔ)在主內(nèi)存中
3、成員變量、static變量、類信息均會(huì)被存儲(chǔ)在主內(nèi)存中
4、主內(nèi)存共享的方式是線程各拷貝一份數(shù)據(jù)到工作內(nèi)存,操作完成后刷新回主內(nèi)存
?
?
?
指令重排序需要滿足的條件
1、在單線程環(huán)境下不能改變程序運(yùn)行的結(jié)果
2、存在數(shù)據(jù)依賴關(guān)系的不允許重排序
無法通過happens-before原則推導(dǎo)出來的,才能進(jìn)行指令的重排序
?
A操作的結(jié)果需要對(duì)B操作可見,則A與B存在happens-before關(guān)系
?
?
volatile : JVM提供的輕量級(jí)同步機(jī)制
1、保證被volatile修飾的共享變量對(duì)所有線程總是可見的
2、禁止指令重排序優(yōu)化
volatile的可見性
1、注意,不是線程安全的,只是可見
?
另外一種寫法:
?
volatile變量為何立即可見?
1、當(dāng)些一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的工作內(nèi)存中的共享變量值刷新到主內(nèi)存中
2、當(dāng)讀取一個(gè)volatile變量時(shí),JMM會(huì)把該線程對(duì)應(yīng)的工作內(nèi)存設(shè)置為無效
?
volatile如何禁止重排優(yōu)化
內(nèi)存屏障
1、保證特定操作的執(zhí)行順序
2、保證某些變量的內(nèi)存可見性
通過插入內(nèi)存屏障指令禁止在內(nèi)存屏障前后的指令執(zhí)行重排序優(yōu)化
強(qiáng)制刷出各種cpu的緩存數(shù)據(jù),因此任何CPU上的線程都能讀取到這些數(shù)據(jù)的最新版本
?
?
上面的操作,看上去沒有問題,但是還是有隱患,有可能會(huì)有指令重排序之后,導(dǎo)致的問題。
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/vingLiu/p/10677428.html
總結(jié)
以上是生活随笔為你收集整理的什么是Java内存模型中的happens-before的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: week3 01
- 下一篇: js如何通过变量调用函数,函数名在变量里