亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

java的內存模型與volatile關鍵字詳解

2019-11-14 08:58:08
字體:
來源:轉載
供稿:網友

由于各種硬件及操作系統的內存訪問差異,java虛擬機使用java內存模型(java Memory Model,JMM)來規范java對內存的訪問。這套模型在jdk 1.2中開始建立,經jdk 1.5的修訂,現已逐步完善起來。

什么是java內存模型

什么是java內存模型,為什么會有這個模型?關于這個問題,就不得不從并發的問題講起。在多核系統中,處理器一般設置緩存來加速數據的讀取,緩存大大提升了程序性能,卻也帶來了“緩存一致性”的新問題。比如,當多個處理器寫同一塊主內存時,以誰的緩存數據為準?讀取、寫入內存的變量需遵循怎樣保證線程安全?針對這些問題,java設計了一套內存模型以用來定義程序中各個變量的訪問規則。

java的內存模型采用的是共享內存的線程通信機制。線程之間的共享變量存儲在主內存中,每個線程都有一個私有的本地內存,本地內存存儲了共享變量的副本。 這里寫圖片描述

圖片來自《深入理解java虛擬機 第2版》

關于共享變量,可以對應為存儲在堆內存的實例變量、類變量及數組元素(堆內存是線程共享的)。私有變量可對應虛擬機棧中的局部變量。事實上,他們是java內存不同層次的劃分,并沒有一定聯系。

內存間的交互操作

要完成主內存與工作內存的交互操作,需遵守一定的規則。java內存模型定義了相當嚴謹而復雜的訪問規則。主要有8種原子性的操作。分別是:lock(鎖定)、unlock(解鎖)、read(讀?。?、load(載入)、use(使用)、assign(賦值)、store(存儲)、write(寫入)。

內存交互時,必須使用以上幾種操作搭配完成,且這8種操作要滿足一定規則。如read和load,store和write必須成對出現;對變量實施use、store時,必須先執行assign和load操作。

幸好,這些難以記憶的規則有一個等效判定的原則,即先行發生原則。

程序次序規則:在一個線程中,程序控制流前面的操作先行發生于后面的操作。監視器鎖規則:一個unlock操作先行發生于對同一個鎖的lock操作。volatile變量規則:對于一個volatile變量,寫操作先行發生于對這個變量的讀操作。傳遞性:如果操作A先行發生于操作B,操作B先行發生于操作C,則操作A先行發生于操作C。

一個內存交互的例子

我們知道java的多線程通信采用共享內存的方式。線程對變量的所有操作都要在工作內存中進行,不能直接訪問主內存。線程間變量傳遞均需主內存間接完成。

這里寫圖片描述

則,線程A要與線程B通信(比如B線程要讀取A線程經操作后的值),需要:

線程A修改本地內存A的值,并將其寫入主內存的共享變量。線程B到主內存讀取線程A修改后的值。

內存模型的3個重要特征

原子性

前面我們提到的8種原子操作都是原子性的,這樣可以保證對基本數據類型的訪問讀寫是原子性的。這里有個例外是JVM沒有強制規定long、double一定是原子操作。但幾乎所有的商業JVM都實現了long、double的原子操作。

可見性

可見性是指,當一個線程修改了共享變量的值,其他變量能得知這個修改。

這里需要引出本文第二個關鍵點:volatile。volatile有兩個語義。這里用其可見性語義。經volatile修飾的變量保證新值能立即同步到主內存中,每次使用前立即從主內存刷新。保證了多線程操作時變量的可見性。后面會有更詳細解釋。

除volatile外,synchronized和final也能實現可見性。 synchronized的可見性由“對一個變量執行unlock前,必須先把此變量同步回主內存”。獲得。

final關鍵字的可見性指:被final修飾的字段在構造器中初始完成,則其他線程就能看到final的值。

有序性

java程序本身具有的有序性可以總結為:如果在同一線程觀察,所有操作都是有序的。而如果在一個線程觀察另一線程,所有操作都是無序的。前部分指在單線程環境中程序的順序性,后部分說的無序是指“指令的重排序”和“工作內存與主內存的同步延遲”。

指令重排序

編譯器能夠自由的以優化的名義去改變指令順序。在特定的環境下,處理器可能會次序顛倒的執行指令。是為指令的重排序。在單線程環境中,程序執行結果不會受到指令重排序的影響。

但有時,我們在多線程情況下,并不希望發生指令重排序來影響并發結果。

java提供了volatile和synchronized來保證線程之間操作的有序性。volatile含有禁止指令重排序的語義(即它的第二個語義),synchronized規定一個變量在同一時刻只允許一條線程對其lock操作,也就是說同一個鎖的兩個同步塊只能串行進入。禁止了指令的重排序。

關于指令重排序,下文還有更多解釋。

volatile語義

介紹完java內存模型的3個特征,現在來詳細介紹volatile及它代表的語義。

準確來說,volatile是java提供的輕量的同步機制。它有兩個特性: 1. 保證修飾的變量對所有線程的可見性。 2. 禁止指令的重排序優化。

根據上面的介紹,我們對可見性及禁止重排序背后的順序性都不陌生。下面我們來詳細說明下。

驗證volatile具有可見性

volatile變量對所有線程是立即可見的,對volatile變量的寫操作都能立即反應到其他線程中。

volatile boolean flag;public void shundown(){ flag = true;}public void doWork(){ while(!flag){ doSomething(); } }

上面的例子即是volatile的典型應用。任一線程調用了shundown()方法,都能保證所有線程執行doWork()時doSomething()方法不執行。

假設flag 不是由volatile修飾,則不能保證內存可見性,當某個線程修改了flag的值后,其他線程不一定會馬上看到或根本看不到,就會引起錯誤。

需注意的是,volatile變量保證可見性時,需滿足以下規則:

運算結果不依賴變量的當前值,或保證只有單一線程修改變量值。(如i++,運算依賴當前值,就不滿足)變量不需要與其他狀態變量共同參與不變約束。public class TestThread2 { public static volatile int race = 0; public static void increase(){ race++; } PRivate static final int THREADS_COUNT =20; public static void main(String[] args) { Thread[] threads = new Thread[THREADS_COUNT]; for(int i=0;i<THREADS_COUNT;i++){ threads[i] = new Thread(()->{ for(int j=0;j<1000;j++){ increase(); } }); threads[i].start(); } System.out.println(race); }}

如上例,若正確并發,則最后應輸出20*1000=20000,可結果總輸出小于20000的結果,且每次都不相同。原因就在于volatile不能保證 race++的可見性。race++ 操作實際上有1.讀取race的值;2.對race加1;3.修改race的值3步操作,而volatile顯然不能保證這些操作的原子性。

volatile禁止指令重排序

指令重排序的語句需遵守一個規則,即as-if-serial語義:

所有操作都可以為了優化而重排序,但必須保證重排序的結果和程序執行結果一致。

這里給出重排序的例子

public class Test { private static int x = 0, y = 0; private static int a = 0, b =0; public static void main(String[] args) throws InterruptedException { int i = 0; while(true) { x = 0; y = 0; a = 0; b = 0; i++; Thread first = new Thread(()->{a = 1;x = b;}); Thread second = new Thread(()->{b = 1;y = a;}); first.start();second.start(); first.join();second.join(); String result = "第" + i + "次 (" + x + "," + y + ")"; if(x == 0 && y == 0) { System.err.println(result); break; } else { System.out.println(result); } } }}

一個線程執行a = 1;x = b;,另一個線程執行b = 1;y = a;,由于a、x,b、y不存在依賴關系,所以有可能發生先執行x=b,然后a=1的指令重排序,經試驗,在多次循環后出現x=b;b=1;y=a;a=1;的線程交替執行結果。即x=0;y=0

這里寫圖片描述

這說明發生了指令重排序,將a,b,x,y用volatile修飾后,運行多次也沒有出現重排序情況。 這里寫圖片描述

一個單例模式的例子

單例模式中的“雙重檢查加鎖”模式如下所示

public class SingletonTest { private volatile static SingletonTest instance = null; private SingletonTest() { } public static SingletonTest getInstance() { if(instance == null) { synchronized (SingletonTest.class){ if(instance == null) { instance = new SingletonTest(); //非原子操作 } } } return instance; }}

上面代碼大家都不陌生,可為什么instance一定要volatile修飾呢?這是由于instance = new SingletonTest();并不是一個原子操作??煞纸鉃椋?/p>memory =allocate(); //分配對象的內存空間 ctorInstance(memory); //初始化對象 instance =memory; //設置instance指向剛分配的內存地址

2操作依賴1操作,但3操作并不依賴2操作,也就是說,上述操作的順序可能為1-2-3,也可能為1-3-2,若是后者,當instance不為空時也可能沒有正確初始化對象,而導致錯誤。

參考

《深入理解java虛擬機 第2版》 java內存模型FAQ深入理解Java內存模型(一)——基礎Java內存訪問重排序的研究
上一篇:快速排序

下一篇:消息隊列

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品亚洲精品| 91网站在线免费观看| 国产精品精品视频一区二区三区| 亚洲国产毛片完整版| 91九色精品视频| 亚洲人成自拍网站| 久久99久国产精品黄毛片入口| 91中文在线观看| 91精品国产九九九久久久亚洲| 欧美成人免费一级人片100| 国产成人精品电影| 国产成人鲁鲁免费视频a| 97av视频在线| 日韩电影中文字幕在线观看| 国产精品第二页| 精品人伦一区二区三区蜜桃免费| 亚洲男人天堂2019| 亚洲一二在线观看| 伊人成人开心激情综合网| 国产精品美女www爽爽爽视频| 亚洲欧美另类在线观看| 亚洲高清av在线| 国产精品自产拍在线观看中文| 亚洲最新中文字幕| 欧美成在线视频| 亚洲国产精久久久久久| 黑人狂躁日本妞一区二区三区| 日韩精品欧美国产精品忘忧草| 国产综合在线观看视频| 欧美性猛交xxxxx免费看| 亚洲中国色老太| 亚洲日本中文字幕免费在线不卡| 亚洲自拍偷拍色片视频| 欧美性猛交xxxx乱大交| 亚洲精品一区久久久久久| 在线观看精品国产视频| 国产亚洲成精品久久| 日韩av网址在线观看| 午夜精品在线观看| 91久久精品久久国产性色也91| 国内精品久久久久久| 亚洲精品久久久久久久久久久久| 国产精品久久久久久婷婷天堂| 国产欧美精品久久久| 在线视频欧美日韩精品| 羞羞色国产精品| 国产日韩换脸av一区在线观看| 国产精品日本精品| 国产精品亚洲片夜色在线| 日韩成人中文字幕在线观看| 日韩在线免费高清视频| 97香蕉超级碰碰久久免费的优势| 国产精品一区二区久久| 中国日韩欧美久久久久久久久| 成人免费xxxxx在线观看| 日本欧美黄网站| 国产99视频精品免视看7| 精品久久香蕉国产线看观看亚洲| 欧美日本啪啪无遮挡网站| 青青久久av北条麻妃黑人| 亚洲免费视频网站| 久久夜色精品国产欧美乱| 亚洲女人天堂成人av在线| 日韩欧中文字幕| www.久久久久| 久久成年人免费电影| www亚洲精品| 亚洲男人的天堂在线播放| 国产亚洲一区精品| 亚洲电影av在线| 国产在线播放91| 中文字幕欧美精品日韩中文字幕| 日韩精品视频在线免费观看| 精品久久香蕉国产线看观看gif| 亚洲丁香婷深爱综合| 欧美成人黑人xx视频免费观看| 欧美日韩国产限制| 日韩欧美在线视频日韩欧美在线视频| 亚洲丁香久久久| 亚洲精品福利在线| 国产亚洲美女久久| 国产精品一区av| 日本道色综合久久影院| 国产日韩欧美在线观看| 国产91精品久久久久久久| 91免费国产视频| 久久精品久久久久| 亚洲视频第一页| 中文字幕亚洲欧美日韩高清| 欧美亚洲日本黄色| 亚洲第一福利在线观看| 国产亚洲精品va在线观看| 91免费国产网站| 亚洲精品美女久久久久| 日韩成人激情影院| 亚洲精品97久久| 欧美性做爰毛片| 最近中文字幕mv在线一区二区三区四区| 免费成人高清视频| 精品综合久久久久久97| 精品香蕉一区二区三区| 中文字幕av日韩| 欧美高跟鞋交xxxxhd| 亚洲片在线观看| 日韩av影视在线| 日韩av免费在线播放| 欧美国产中文字幕| 久久男人的天堂| 欧美性猛交丰臀xxxxx网站| 97久久精品在线| 国产欧美一区二区三区久久人妖| 久久久亚洲精品视频| 日本一欧美一欧美一亚洲视频| 国产精品久久一区主播| 在线成人中文字幕| 91精品国产色综合久久不卡98| 午夜免费日韩视频| 欧美视频中文在线看| 亚洲午夜国产成人av电影男同| 国产成人综合一区二区三区| 国产精品最新在线观看| 久久久久国产精品一区| 亚洲人成电影在线| 日韩一区av在线| 久久亚洲春色中文字幕| 最近2019免费中文字幕视频三| 亚洲人成电影网站色www| 91久久精品日日躁夜夜躁国产| 欧美另类极品videosbestfree| 久久夜色撩人精品| 亚洲人a成www在线影院| 亚洲最大成人在线| 色偷偷9999www| 精品国产依人香蕉在线精品| 欧美人成在线视频| 国产成人av网| 久久99精品久久久久久琪琪| 欧美在线免费看| 成人信息集中地欧美| 亚洲国内高清视频| 日韩免费高清在线观看| 欧美性jizz18性欧美| 日韩中文字幕在线视频| www欧美日韩| 久久97精品久久久久久久不卡| 国产成人高清激情视频在线观看| 57pao成人国产永久免费| 91亚洲精华国产精华| 欧美性videos高清精品| 午夜精品在线观看| 久久久久久久激情视频| 亚洲人成在线播放| 一区二区中文字幕| 亚洲人成自拍网站| 国产手机视频精品| 欧美亚洲国产日本| 国产精品观看在线亚洲人成网| 久久久久久91香蕉国产| 日韩av电影手机在线| 欧美成人亚洲成人| 色综合老司机第九色激情| 欧美日韩成人黄色| 亚洲韩国日本中文字幕| 欧美国产日韩中文字幕在线|