|
Java內(nèi)存模型是圍繞著并發(fā)編程中原子性、可見性、有序性這三個(gè)特征來建立的,那我們依次看一下這三個(gè)特征:
原子性(Atomicity)
原子性是指一個(gè)操作不能被打斷,要么全部執(zhí)行完畢,要么不執(zhí)行。在這點(diǎn)上有點(diǎn)類似于事務(wù)操作,要么全部執(zhí)行成功,要么回退到執(zhí)行該操作之前的狀態(tài)。
基本類型數(shù)據(jù)的訪問大都是原子操作,long 和double類型的變量是64位,但是在32位JVM中,32位的JVM會(huì)將64位數(shù)據(jù)的讀寫操作分為2次32位的讀寫操作來進(jìn)行,這就導(dǎo)致了long、double類型的變量在32位虛擬機(jī)中是非原子操作,數(shù)據(jù)有可能會(huì)被破壞,也就意味著多個(gè)線程在并發(fā)訪問的時(shí)候是線程非安全的。
可見性
一個(gè)線程對(duì)共享變量做了修改之后,-的線程立即能夠看到(感知到)該變量這種修改(變化)。
Java內(nèi)存模型是通過將在工作內(nèi)存中的變量修改后的值同步到主內(nèi)存,在讀取變量前從主內(nèi)存刷新最新值到工作內(nèi)存中,這種依賴主內(nèi)存的方式來實(shí)現(xiàn)可見性的。
無論是普通變量還是volatile變量都是如此,區(qū)別在于:volatile的特殊規(guī)則保證了volatile變量值修改后的新值立刻同步到主內(nèi)存,每次使用volatile變量前立即從主內(nèi)存中刷新,因此volatile保證了多線程之間的操作變量的可見性,而普通變量則不能保證這一點(diǎn)。
除了volatile關(guān)鍵字能實(shí)現(xiàn)可見性之外,還有syn*onized,Lock,final也是可以的。
使用syn*onized關(guān)鍵字,在同步方法/同步塊開始時(shí)(Monitor Enter),使用共享變量時(shí)會(huì)從主內(nèi)存中刷新變量值到工作內(nèi)存中(即從主內(nèi)存中讀取最新值到線程私有的工作內(nèi)存中),在同步方法/同步塊結(jié)束時(shí)(Monitor Exit),會(huì)將工作內(nèi)存中的變量值同步到主內(nèi)存中去(即將線程私有的工作內(nèi)存中的值寫入到主內(nèi)存進(jìn)行同步)。
使用Lock接口的最常用的實(shí)現(xiàn)ReentrantLock(重入鎖)來實(shí)現(xiàn)可見性:當(dāng)我們?cè)诜椒ǖ拈_始位置執(zhí)行lock.lock()方法,這和syn*onized開始位置(Monitor Enter)有相同的語義,即使用共享變量時(shí)會(huì)從主內(nèi)存中刷新變量值到工作內(nèi)存中(即從主內(nèi)存中讀取最新值到線程私有的工作內(nèi)存中),在方法的最后finally塊里執(zhí)行lock.unlock()方法,和syn*onized結(jié)束位置(Monitor Exit)有相同的語義,即會(huì)將工作內(nèi)存中的變量值同步到主內(nèi)存中去(即將線程私有的工作內(nèi)存中的值寫入到主內(nèi)存進(jìn)行同步)。
final關(guān)鍵字的可見性是指:被final修飾的變量,在構(gòu)造函數(shù)數(shù)一旦初始化完成,并且在構(gòu)造函數(shù)中并沒有把“this”的引用傳遞出去(“this”引用逃逸是很危險(xiǎn)的,-的線程很可能通過該引用訪問到只“初始化一半”的對(duì)象),那么-線程就可以看到final變量的值。
有序性
對(duì)于一個(gè)線程的代碼而言,我們總是以為代碼的執(zhí)行是從前往后的,依次執(zhí)行的。這么說不能說完全不對(duì),在單線程程序里,確實(shí)會(huì)這樣執(zhí)行;但是在多線程并發(fā)時(shí),程序的執(zhí)行就有可能出現(xiàn)亂序。用一句話可以總結(jié)為:在本線程內(nèi)觀察,操作都是有序的;如果在一個(gè)線程中觀察另外一個(gè)線程,所有的操作都是無序的。前半句是指“線程內(nèi)表現(xiàn)為串行語義(WithIn Thread As-if-Serial Semantics)”,后半句是指“指令重排”現(xiàn)象和“工作內(nèi)存和主內(nèi)存同步延遲”現(xiàn)象。
Java提供了兩個(gè)關(guān)鍵字volatile和syn*onized來保證多線程之間操作的有序性,volatile關(guān)鍵字本身通過加入內(nèi)存屏障來禁止指令的重排序,而syn*onized關(guān)鍵字通過一個(gè)變量在同一時(shí)間只允許有一個(gè)線程對(duì)其進(jìn)行加鎖的規(guī)則來實(shí)現(xiàn),在單線程程序中,不會(huì)發(fā)生“指令重排”和“工作內(nèi)存和主內(nèi)存同步延遲”現(xiàn)象,只在多線程程序中出現(xiàn)。
在Java語言中,采用的是共享內(nèi)存模型來實(shí)現(xiàn)多線程之間的信息交換和數(shù)據(jù)同步的。Java內(nèi)存模型的主要目標(biāo)是定義程序中各個(gè)變量的訪問規(guī)則,即在JVM中將變量存儲(chǔ)到內(nèi)存和從內(nèi)存中取出變量這樣的底層細(xì)節(jié)。更多Java的學(xué)習(xí)內(nèi)容歡迎大家加入千鋒大家庭一起交流學(xué)習(xí)。
千鋒教育:http://www.mobiletrain.org/
千鋒深圳校區(qū):http://sz.qfedu.com/?pinzhuan=biaoti
深圳西部硅谷校區(qū)地址:深圳市寶安區(qū)寶安大道5010號(hào)深圳西部硅谷A區(qū)B座605-619
深圳大學(xué)城校區(qū)地址:深圳市南山區(qū)留仙大道1201號(hào)大學(xué)城創(chuàng)客小鎮(zhèn)16棟2樓、3樓
培訓(xùn)咨詢專線:0755-33582485-801(硅谷校區(qū))0755-86660670-801(大學(xué)城校區(qū))
咨 詢 QQ : 1660794050
面授課程:全棧HTML5+培訓(xùn)、UI交互設(shè)計(jì)培訓(xùn)、PHP培訓(xùn)、Java+云數(shù)據(jù)培訓(xùn)、大數(shù)據(jù)開發(fā)培訓(xùn)、VR/AR/Unity游戲開發(fā)培訓(xùn)、Python培訓(xùn)、Linux云計(jì)算培訓(xùn)、全棧軟件測(cè)試培訓(xùn)、Android培訓(xùn)、iOS培訓(xùn)、好程序員
企業(yè)級(jí)別:未認(rèn)證 我要認(rèn)證
聯(lián) 系 人:李老師(先生)
公司電話:4001869990
在線狀態(tài): [當(dāng)前離線]
所在地區(qū):北京
按字母索引  : a b c d e f g h i j k l m n o p q r s t u v w x y z
網(wǎng)站首頁 | 付款方式 | 關(guān)于我們 | 聯(lián)系方式 | 服務(wù)條款 | 版權(quán)隱私 | 網(wǎng)站地圖 | 排名推廣 | 廣告服務(wù) | 積分換禮 | 網(wǎng)站留言 | RSS訂閱 | TOP365 | 鄂ICP備14015623號(hào)-23
?2007-2023 鴻通網(wǎng)(www.rxmyw.cn)是專業(yè)的B2B綜合門戶站,提供生產(chǎn)廠家的電子商務(wù)供求服務(wù),是企業(yè)尋求b2b電子商務(wù)網(wǎng)絡(luò)貿(mào)易信息的首選平臺(tái)!鄂公網(wǎng)安備42018502006975