国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Java多線程編程從一個(gè)錯(cuò)誤的雙重校驗(yàn)鎖代碼談一下volatile關(guān)鍵字

在Java多線程編程-(2)中提及到了一段使用Synchronized關(guān)鍵字實(shí)現(xiàn)的單利模式--雙重校驗(yàn)鎖,代碼如下:

慧眼的小伙伴,已經(jīng)發(fā)現(xiàn)了其中的問題,并給了及時(shí)的回復(fù):

這也是我今天準(zhǔn)備和大家一起學(xué)習(xí)的內(nèi)容。上述的代碼是錯(cuò)誤的寫法,之所以是錯(cuò)誤的,這是因?yàn)椋?strong>指令重排優(yōu)化,可能會(huì)導(dǎo)致初始化單利對(duì)象和將該對(duì)象地址賦值給instance字段的順序與上面Java代碼中書寫的順序不同。

例如:線程A在創(chuàng)建單例對(duì)象時(shí),在構(gòu)造方法被調(diào)用之前,就為該對(duì)象分配了內(nèi)存空間并將對(duì)象設(shè)置為默認(rèn)值。此時(shí)線程A就可以將分配的內(nèi)存地址賦值給instance字段了,然而該對(duì)象可能還沒有完成初始化操作。線程B來調(diào)用newInstance()方法,得到的就是為初始化完全的單例對(duì)象,這就會(huì)導(dǎo)致系統(tǒng)出現(xiàn)異常行為。

為了解決上述的問題,可以使用volatile關(guān)鍵字進(jìn)行修飾instance字段。volatile關(guān)鍵字在這里的含義就是禁止指令的重排序優(yōu)化(另一個(gè)作用是提供內(nèi)存可見性),從而保證instance字段被初始化時(shí),單例對(duì)象已經(jīng)被完全初始化。

最終代碼如下:

那么問題來了,為什么volatile關(guān)鍵字可以實(shí)現(xiàn)禁止指令的重排序優(yōu)化以及什么是指令重排序優(yōu)化哪?

在Java內(nèi)存模型中我們都是圍繞著原子性、有序性和可見性進(jìn)行討論的。為了確保線程間的原子性、有序性和可見性,Java中使用了一些特殊的關(guān)鍵字申明或者是特殊的操作來告訴虛擬機(jī),在這個(gè)地方,要注意一下,不能隨意變動(dòng)優(yōu)化目標(biāo)指令。關(guān)鍵字volatile就是其中之一。

指令重排序是JVM為了優(yōu)化指令,提高程序運(yùn)行效率,在不影響單線程程序執(zhí)行結(jié)果的前提下,盡可能地提高并行度(比如:將多條指定并行執(zhí)行或者是調(diào)整指令的執(zhí)行順序)。編譯器、處理器也遵循這樣一個(gè)目標(biāo)。注意是單線程??娠@而知,多線程的情況下指令重排序就會(huì)給程序員帶來問題。

最重要的一個(gè)問題就是程序執(zhí)行的順序可能會(huì)被調(diào)整,另一個(gè)問題是對(duì)修改的屬性無法及時(shí)的通知其他線程,已達(dá)到所有線程操作該屬性的可見性。

根據(jù)編譯器的優(yōu)化規(guī)則,如果不使用volatile關(guān)鍵字對(duì)變量進(jìn)行修飾的,那么這個(gè)變量被修改后,其他線程可能并不會(huì)被通知到,甚至在別的想愛你城中,看到變量修改順序都會(huì)是反的。一旦使用volatile關(guān)鍵字進(jìn)行修飾的話,虛擬機(jī)就會(huì)特別小心的處理這種情況。

因此,如何正確的使用雙重校驗(yàn)鎖,以及為什么使用關(guān)鍵字volatile這里我們應(yīng)該很清楚了。

上述也提到了volatile關(guān)鍵字的另一個(gè)作用就是:變量在多個(gè)線程之間可見。

volatile可見性

首先我們先看一下段代碼:

執(zhí)行結(jié)果:

可以看出 在單線程的情況下,程序會(huì)一直執(zhí)行下去,即一直執(zhí)行while循環(huán),導(dǎo)致程序不能正常執(zhí)行下邊的代碼。解決的方法可以使用多線程。多線程示例代碼如下:

執(zhí)行結(jié)果如下:

可以看出使用多線程的技術(shù)實(shí)現(xiàn),但是有一個(gè)問題就是在一些平臺(tái)上執(zhí)行的時(shí)候會(huì)出現(xiàn)死鎖的情況,解決的方法就是使用volatile關(guān)鍵字。即變量用volatile關(guān)鍵字修飾。

volatile關(guān)鍵字的作用就是強(qiáng)制從公共堆棧中取得變量的值,而不是線程私有的數(shù)據(jù)棧中取得變量的值。

volatile與synchronized的區(qū)別

1、關(guān)鍵字volatile是線程同步的輕量級(jí)實(shí)現(xiàn),性能比synchronized要好,并且volatile只能修于變量,而synchronized可以修飾方法,代碼塊等。

2、多線程訪問volatile不會(huì)發(fā)生阻塞,而synchronized會(huì)發(fā)生阻塞。

3、volatile可以保證數(shù)據(jù)的可見性,但不可以保證原子性,而synchronized可以保證原子性,也可以間接保證可見性,因?yàn)樗麜?huì)將私有內(nèi)存和公共內(nèi)存中的數(shù)據(jù)做同步。

4、volatile解決 的是變量在多個(gè)線程之間的可見性,而synchronized解決的是多個(gè)線程之間訪問資源的同步性。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
學(xué)習(xí)Java多線程之volatile域
Java并發(fā)入門原理教程(三)
你見過這樣的單例模式嗎?
Java開發(fā)之多線程的基本概念與如何避坑
7張圖帶你輕松理解Java 線程安全
快速掌握并發(fā)編程---深入了解volatile
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服