Java并发编程 Volatile关键字解析
生活随笔
收集整理的這篇文章主要介紹了
Java并发编程 Volatile关键字解析
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
volatile關(guān)鍵字的兩層語(yǔ)義 一旦一個(gè)共享變量(類(lèi)的成員變量、類(lèi)的靜態(tài)成員變量)被volatile修飾之后,那么就具備了兩層語(yǔ)義: 1)保證了不同線程對(duì)這個(gè)變量進(jìn)行操作時(shí)的可見(jiàn)性,即一個(gè)線程修改了某個(gè)變量的值,這新值對(duì)其他線程來(lái)說(shuō)是立即可見(jiàn)的。 2)禁止進(jìn)行指令重排序。 根據(jù)volatile的語(yǔ)義,我們可以看到,volatile主要針對(duì)的是并發(fā)三要素(原子性,可見(jiàn)性和有序性)中的后兩者有實(shí)際優(yōu)化作用。 可見(jiàn)性: 線程本身并不直接與主內(nèi)存進(jìn)行數(shù)據(jù)的交互,而是通過(guò)線程的工作內(nèi)存來(lái)完成相應(yīng)的操作。這也是導(dǎo)致線程間數(shù)據(jù)不可見(jiàn)的本質(zhì)原因。因此要實(shí)現(xiàn)volatile變量的可見(jiàn)性,直接從這方面入手即可。對(duì)volatile變量的寫(xiě)操作與普通變量的主要區(qū)別有兩點(diǎn): (1)修改volatile變量時(shí)會(huì)強(qiáng)制將修改后的值刷新的主內(nèi)存中。 (2)修改volatile變量后會(huì)導(dǎo)致其他線程工作內(nèi)存中對(duì)應(yīng)的變量值失效。因此,再讀取該變量值的時(shí)候就需要重新從讀取主內(nèi)存中的值。 通過(guò)這兩個(gè)操作,就可以解決volatile變量的可見(jiàn)性問(wèn)題。 有序性: volatile會(huì)觸發(fā)jvm的內(nèi)存屏障策略 內(nèi)存屏障策略: (1)LoadLoad 屏障 執(zhí)行順序:Load1—>Loadload—>Load2 確保Load2及后續(xù)Load指令加載數(shù)據(jù)之前能訪問(wèn)到Load1加載的數(shù)據(jù)。 (2)StoreStore 屏障 執(zhí)行順序:Store1—>StoreStore—>Store2 確保Store2以及后續(xù)Store指令執(zhí)行前,Store1操作的數(shù)據(jù)對(duì)其它處理器可見(jiàn)。 (3)LoadStore 屏障 執(zhí)行順序: Load1—>LoadStore—>Store2 確保Store2和后續(xù)Store指令執(zhí)行前,可以訪問(wèn)到Load1加載的數(shù)據(jù)。 (4)StoreLoad 屏障 執(zhí)行順序: Store1—> StoreLoad—>Load2 每次對(duì)volatile進(jìn)行讀寫(xiě)操作,根據(jù)上述表格,會(huì)觸發(fā)對(duì)應(yīng)的CPU指令,從線程內(nèi)存緩沖區(qū)將之前更改的變量刷入主存。 簡(jiǎn)單來(lái)說(shuō),volatile會(huì)在一定程度上影響jvm指令集的優(yōu)化策略,在volatile之前和之后的指令集不會(huì)亂序越過(guò)volatile變量執(zhí)行。暫時(shí)volatile之前和之后的指令集在沒(méi)有關(guān)聯(lián)性的前提下,jvm可以亂序執(zhí)行。 jvm的volatile策略,在一定程度上,打折扣地實(shí)現(xiàn)了jvm的happens-before原則(先行發(fā)生原則),如下所述。
- 程序次序規(guī)則:一個(gè)線程內(nèi),按照代碼順序,書(shū)寫(xiě)在前面的操作先行發(fā)生于書(shū)寫(xiě)在后面的操作
- 鎖定規(guī)則:一個(gè)unLock操作先行發(fā)生于后面對(duì)同一個(gè)鎖額lock操作
- volatile變量規(guī)則:對(duì)一個(gè)變量的寫(xiě)操作先行發(fā)生于后面對(duì)這個(gè)變量的讀操作
- 傳遞規(guī)則:如果操作A先行發(fā)生于操作B,而操作B又先行發(fā)生于操作C,則可以得出操作A先行發(fā)生于操作C
- 線程啟動(dòng)規(guī)則:Thread對(duì)象的start()方法先行發(fā)生于此線程的每個(gè)一個(gè)動(dòng)作
- 線程中斷規(guī)則:對(duì)線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測(cè)到中斷事件的發(fā)生
- 線程終結(jié)規(guī)則:線程中所有的操作都先行發(fā)生于線程的終止檢測(cè),我們可以通過(guò)Thread.join()方法結(jié)束、Thread.isAlive()的返回值手段檢測(cè)到線程已經(jīng)終止執(zhí)行
- 對(duì)象終結(jié)規(guī)則:一個(gè)對(duì)象的初始化完成先行發(fā)生于他的finalize()方法的開(kāi)始
volatile常見(jiàn)使用場(chǎng)景:
(1)狀態(tài)標(biāo)記量
(2)單例模式一次性安全發(fā)布
(3)低開(kāi)銷(xiāo)讀寫(xiě)鎖
?
?
參考文檔: 《Java并發(fā)編程:Volatile關(guān)鍵字解析》http://www.cnblogs.com/dolphin0520/p/3920373.html 《Java多線程:volatile變量,happens-before關(guān)系及內(nèi)存一致性》http://www.importnew.com/17149.html 《Java并發(fā)編程:volatile的使用及其原理》http://www.cnblogs.com/paddix/p/5428507.html 《Java理論與實(shí)踐:正確使用Volatile變量》https://www.ibm.com/developerworks/cn/java/j-jtp06197.html?
轉(zhuǎn)載于:https://www.cnblogs.com/researchboy/p/researchboy.html
總結(jié)
以上是生活随笔為你收集整理的Java并发编程 Volatile关键字解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux下修改rm命令防止误删除
- 下一篇: Java学习lesson 02