(三)volatile關(guān)鍵字(1)

概要:5 Happens-before、6有序性?

阻止(偽)編譯器認(rèn)為的無法“被代碼本身”改變代碼(變量/對象)進(jìn)行優(yōu)化

?JDK1.2 前,Java內(nèi)存模型實(shí)現(xiàn)總是從主存(即共享內(nèi)存)讀取變量。當(dāng)前內(nèi)存模型,線程可以把變量保存本地內(nèi)存(機(jī)器寄存器),不直接在主存中讀寫。線程主存中修改,另一個線程繼續(xù)用寄存器中值(拷貝),造成數(shù)據(jù)的不一致。?

解決:變量聲明為?volatile,指示 JVM,這個變量不穩(wěn)定,每次使用它到主存中讀取。?


二 volatile關(guān)鍵字的可見性

volatile 修飾的變量,強(qiáng)迫從主存中讀寫不同線程看到變量同一個值,保證可見性。

isRunning變量沒有加上volatile關(guān)鍵字時,死循環(huán),isRunning被修改但是沒有被寫到主存中,線程本地內(nèi)存中一直為true

while里加輸出sleep死循環(huán)也會停,不管是否volatile關(guān)鍵字。

JVM會盡力保證內(nèi)存的可見性,只要CPU有時間,JVM會盡力去保證變量值的更新。

不同volatile強(qiáng)制保證可見性。CPU占用,JVM不強(qiáng)制CPU去取最新值。加輸出或sleep后,有時間去保證內(nèi)存可見性

三 無法保證對變量原子性

自增操作(非原子操作)上不保證(個人感覺有問題)

MyThread.java
Run.java

運(yùn)行結(jié)果:上面的“count=i;”是一個原子操作,大部分都是正確結(jié)果99,也有部分不是99的結(jié)果。?

解決辦法

使用synchronized關(guān)鍵字加鎖。(這只是一種方法,Lock和AtomicInteger原子類都可以)

四 synchronized關(guān)鍵字和volatile關(guān)鍵字比較

1.volatile輕量級性能好;只用于變量;不會阻塞

synchronized可方法、代碼塊。會阻塞;1.6后效提升,實(shí)際用的多。

2.volatile解決可見性,不能原子性。synchronized解決同步性,都能保證。

五、Happens-before

A Happens-before B:A對B可見。Happens-before原則:

1)順序規(guī)則:線程中,按照控制流順序,前面Happens-Before后續(xù)

2)volatile變量規(guī)則:volatile寫操作Happens-Before于后續(xù)讀操作(時間上)

3)傳遞性規(guī)則:A Happens-Before B 且 B Happens-Before C,那么A Happens-Before C

4)鎖的規(guī)則:解鎖Happens-Before于后續(xù)加鎖。(時間上)

5)線程start()規(guī)則:主線程A啟動B start(),start() Happens-Before B任意操作

6)線程join()規(guī)則:主線程A等待子線程B完成(主線程A調(diào)用子線程B的join()方法),當(dāng)子線程B完成后,主線程能夠看到子線程的操作(指的是對共享變量的操作)。

7)線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生與被中斷線程代碼檢測到中斷事件的發(fā)生,可以通過Thread.interrupted()檢測是否發(fā)生中斷。

8)對象終結(jié)規(guī)則:一個對象的初始化的完成,也就是構(gòu)造函數(shù)執(zhí)行的結(jié)束一定Happens-Before它的finalize()方法。

ps:與時間先后順序沒關(guān)系,以Happens-Before原則為準(zhǔn)

六、volatile解決有序性問題

依賴Happens-before前3條規(guī)則。A先于B,A對B可見

x(沒有volatile)有沒有可能等于0,因?yàn)?b>編譯優(yōu)化帶來指令重排,導(dǎo)致v = true 先于x = 42執(zhí)行,reader()正好在兩者之間執(zhí)行,用volatile修飾后,再分析:

1、先看Happens-Before第二條(寫先于讀),賦值判斷,writer()對v賦值,reader()判斷v值true后,說明v寫先讀。

2、結(jié)合Happens-Before第一條,可以得出

????????x = 42 Happens-Before v = true

????????v = true Happens-Before if(v)(判斷為true時)

????????if(v) Happens-Before System.out.println(x)

3、再結(jié)合Happens-Before第三條傳遞性,? x取值只能是42。

? ? ? ? x = 42 Happens-Before System.out.println(x)


https://blog.csdn.net/zcyt085/article/details/108309917

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容