|
Java內存模型是圍繞著并發(fā)編程中原子性、可見性、有序性這三個特征來建立的,那我們依次看一下這三個特征:
原子性(Atomicity)
原子性是指一個操作不能被打斷,要么全部執(zhí)行完畢,要么不執(zhí)行。在這點上有點類似于事務操作,要么全部執(zhí)行成功,要么回退到執(zhí)行該操作之前的狀態(tài)。
基本類型數據的訪問大都是原子操作,long 和double類型的變量是64位,但是在32位JVM中,32位的JVM會將64位數據的讀寫操作分為2次32位的讀寫操作來進行,這就導致了long、double類型的變量在32位虛擬機中是非原子操作,數據有可能會被破壞,也就意味著多個線程在并發(fā)訪問的時候是線程非安全的。
可見性
一個線程對共享變量做了修改之后,-的線程立即能夠看到(感知到)該變量這種修改(變化)。
Java內存模型是通過將在工作內存中的變量修改后的值同步到主內存,在讀取變量前從主內存刷新最新值到工作內存中,這種依賴主內存的方式來實現可見性的。
無論是普通變量還是volatile變量都是如此,區(qū)別在于:volatile的特殊規(guī)則保證了volatile變量值修改后的新值立刻同步到主內存,每次使用volatile變量前立即從主內存中刷新,因此volatile保證了多線程之間的操作變量的可見性,而普通變量則不能保證這一點。
除了volatile關鍵字能實現可見性之外,還有syn*onized,Lock,final也是可以的。
使用syn*onized關鍵字,在同步方法/同步塊開始時(Monitor Enter),使用共享變量時會從主內存中刷新變量值到工作內存中(即從主內存中讀取最新值到線程私有的工作內存中),在同步方法/同步塊結束時(Monitor Exit),會將工作內存中的變量值同步到主內存中去(即將線程私有的工作內存中的值寫入到主內存進行同步)。
使用Lock接口的最常用的實現ReentrantLock(重入鎖)來實現可見性:當我們在方法的開始位置執(zhí)行lock.lock()方法,這和syn*onized開始位置(Monitor Enter)有相同的語義,即使用共享變量時會從主內存中刷新變量值到工作內存中(即從主內存中讀取最新值到線程私有的工作內存中),在方法的最后finally塊里執(zhí)行lock.unlock()方法,和syn*onized結束位置(Monitor Exit)有相同的語義,即會將工作內存中的變量值同步到主內存中去(即將線程私有的工作內存中的值寫入到主內存進行同步)。
final關鍵字的可見性是指:被final修飾的變量,在構造函數數一旦初始化完成,并且在構造函數中并沒有把“this”的引用傳遞出去(“this”引用逃逸是很危險的,-的線程很可能通過該引用訪問到只“初始化一半”的對象),那么-線程就可以看到final變量的值。
有序性
對于一個線程的代碼而言,我們總是以為代碼的執(zhí)行是從前往后的,依次執(zhí)行的。這么說不能說完全不對,在單線程程序里,確實會這樣執(zhí)行;但是在多線程并發(fā)時,程序的執(zhí)行就有可能出現亂序。用一句話可以總結為:在本線程內觀察,操作都是有序的;如果在一個線程中觀察另外一個線程,所有的操作都是無序的。前半句是指“線程內表現為串行語義(WithIn Thread As-if-Serial Semantics)”,后半句是指“指令重排”現象和“工作內存和主內存同步延遲”現象。
Java提供了兩個關鍵字volatile和syn*onized來保證多線程之間操作的有序性,volatile關鍵字本身通過加入內存屏障來禁止指令的重排序,而syn*onized關鍵字通過一個變量在同一時間只允許有一個線程對其進行加鎖的規(guī)則來實現,在單線程程序中,不會發(fā)生“指令重排”和“工作內存和主內存同步延遲”現象,只在多線程程序中出現。
在Java語言中,采用的是共享內存模型來實現多線程之間的信息交換和數據同步的。Java內存模型的主要目標是定義程序中各個變量的訪問規(guī)則,即在JVM中將變量存儲到內存和從內存中取出變量這樣的底層細節(jié)。更多Java的學習內容歡迎大家加入千鋒大家庭一起交流學習。
千鋒教育:http://www.mobiletrain.org/
千鋒深圳校區(qū):http://sz.qfedu.com/?pinzhuan=biaoti
深圳西部硅谷校區(qū)地址:深圳市寶安區(qū)寶安大道5010號深圳西部硅谷A區(qū)B座605-619
深圳大學城校區(qū)地址:深圳市南山區(qū)留仙大道1201號大學城創(chuàng)客小鎮(zhèn)16棟2樓、3樓
培訓咨詢專線:0755-33582485-801(硅谷校區(qū))0755-86660670-801(大學城校區(qū))
咨 詢 QQ : 1660794050
面授課程:全棧HTML5+培訓、UI交互設計培訓、PHP培訓、Java+云數據培訓、大數據開發(fā)培訓、VR/AR/Unity游戲開發(fā)培訓、Python培訓、Linux云計算培訓、全棧軟件測試培訓、Android培訓、iOS培訓、好程序員