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

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

JVM并發機制探討—內存模型、內存可見性和指令重排序

2019-11-11 04:50:53
字體:
來源:轉載
供稿:網友

并發本來就是個有意思的問題,尤其是現在又流行這么一句話:“高帥富加機器,窮矮搓搞優化”。從這句話可以看到,無論是高帥富還是窮矮搓都需要深入理解并發編程,高帥富加多了機器,需要協調多臺機器或者多個CPU對共享資源的訪問,因此需要了解并發,窮矮搓搞優化需要編寫各種多線程的代碼來壓榨 CPU的計算資源,讓它在同一時刻做更多的事情,這個更需要了解并發。

在我前一篇關于并發的文章http://my.oschina.NET/chihz/blog/54731中提到過管程,管程的特色是在編程語言中 對并發的細節進行封裝,使程序員可以直接在語言中就得到并發的支持,而不必自己去處理一些像是控制信號量之類容易出錯且繁瑣的細節問題。一些語言是通過在 編譯時解開語法糖的方式去實現管程,但java在編譯后生成的字節碼層面上對并發仍然是一層封裝,比如syncrhonized塊在編譯之后只是對應了兩 條指令:monitorenter和monitorexit。更多的并發細節是在JVM運行時去處理的,而不是編譯。這篇文章主要是針對JVM處理并發的 一些細節的探討。

JAVA內存模型

對于我們平時開發的業務應用來說,內存應該是訪問速度最快的存儲設備,對于頻繁訪問的數據,我們總是習慣把它們放到內存緩存中,有句話不是說么,緩 存就像是清涼油,哪里有問題就抹一抹。但是CPU的運算速度比起內存的訪問速度還要快幾個量級,為了平衡這個差距,于是就專門為CPU引入了高速緩存,頻 繁使用的數據放到高速緩存當中,CPU在使用這些數據進行運算的時候就不必再去訪問內存。但是在多CPU時代卻有一個問題,每個CPU都擁有自己的高速緩 存,內存又是所有CPU共享的公共資源,于是內存此時就成了一個臨界區,如果控制不好各個CPU對內存的并發訪問,那么就會產生錯誤,出現數據不一致的情 況。為了避免這種情況,需要采取緩存一致性協議來保證,這類協議有很多,各個硬件平臺和操作系統的實現不盡相同。

JVM需要實現跨平臺的支持,它需要有一套自己的同步協議來屏蔽掉各種底層硬件和操作系統的不同,因此就引入了Java內存模型。對于Java來說 開發者并不需要關心任何硬件細節,因此沒有多核CPU和高速緩存的概念,多核CPU和高速緩存在JVM中對應的是Java語言內置的線程和每個線程所擁有 的獨立內存空間,Java內存模型所規范的也就是數據在線程自己的獨立內存空間和JVM共享內存之間同步的問題。下面這兩張圖說明了硬件平臺和JVM內存 模型的相似和差異之處。

CPU緩存和內存模型

JVM線程內存模型

Java內存模型規定,對于多個線程共享的變量,存儲在主內存當中,每個線程都有自己獨立的工作內存,線程只能訪問自己的工作內存,不可以訪問其它 線程的工作內存。工作內存中保存了主內存共享變量的副本,線程要操作這些共享變量,只能通過操作工作內存中的副本來實現,操作完畢之后再同步回到主內存當 中。如何保證多個線程操作主內存的數據完整性是一個難題,Java內存模型也規定了工作內存與主內存之間交互的協議,首先是定義了8種原子操作:

(1) lock:將主內存中的變量鎖定,為一個線程所獨占

(2) unclock:將lock加的鎖定解除,此時其它的線程可以有機會訪問此變量

(3) read:將主內存中的變量值讀到工作內存當中

(4) load:將read讀取的值保存到工作內存中的變量副本中。

(5) use:將值傳遞給線程的代碼執行引擎

(6) assign:將執行引擎處理返回的值重新賦值給變量副本

(7) store:將變量副本的值存儲到主內存中。

(8) write:將store存儲的值寫入到主內存的共享變量當中。

我們可以看到,要保證數據的同步,lock和unlock定義了一個線程訪問一次共享內存的界限,有lock操作也必須有unlock操作,另外一 些操作也必須要成對出現才可以,像是read和load、store和write需要成對出現,如果單一指令出現,那么就會造成數據不一致的問題。 Java內存模型也針對這些操作指定了必須滿足的規則:

(1) read和load、store和write必須要成對出現,不允許單一的操作,否則會造成從主內存讀取的值,工作內存不接受或者工作內存發起的寫入操作而主內存無法接受的現象。

(2) 在線程中使用了assign操作改變了變量副本,那么就必須把這個副本通過store-write同步回主內存中。如果線程中沒有發生assign操作,那么也不允許使用store-write同步到主內存。

(3) 在對一個變量實行use和store操作之前,必須實行過load和assign操作。

(4) 變量在同一時刻只允許一個線程對其進行lock,有多少次lock操作,就必須有多少次unlock操作。在lock操作之后會清空此變量在工作內存中原 先的副本,需要再次從主內存read-load新的值。在執行unlock操作前,需要把改變的副本同步回主存。

內存可見性

通過上面Java內存模型的概述,我們會注意到這么一個問題,每個線程在獲取鎖之后會在自己的工作內存來操作共享變量,在工作內存中的副本回寫到主 內存,并且其它線程從主內存將變量同步回自己的工作內存之前,共享變量的改變對其它線程是不可見的。那么很多時候我們需要一個線程對共享變量的改動,其它 線程也需要立即得知這個改動該怎么辦呢?比如以下的情景,有一個全局的狀態變量open:

boolean open= true; 

這個變量用來描述對一個資源的打開關閉狀態,true表示打開,false表示關閉,假設有一個線程A,在執行一些操作后將open修改為false:

//線程A

resource.close();  open = false;  

線程B隨時關注open的狀態,當open為true的時候通過訪問資源來進行一些操作:

//線程B

while(open) {    doSomethingWithResource(resource);  }  

當A把資源關閉的時候,open變量對線程B不可見,如果此時open變量的改動尚未同步到線程B的工作內存中,那么線程B就會用一個已經關閉了的資源去做一些操作,因此產生錯誤。

所以對于上面的情景,要求一個線程對open的改變,其他的線程能夠立即可見,Java為此提供了volatile關鍵字,在聲明open變量的時 候加入volatile關鍵字就可以保證open的內存可見性,即open的改變對所有的線程都是立即可見的。volatile保證可見性的原理是在每次 訪問變量時都會進行一次刷新,因此每次訪問都是主內存中最新的版本。

指令重排序

很多介紹JVM并發的書或文章都會談到JVM為了優化性能,采用了指令重排序,但是對于什么是指令重排序,為什么重排序會優化性能卻很少有提及,其實道理很簡單,假設有這么兩個共享變量a和b:

PRivate int a;  private int b;  

在線程A中有兩條語句對這兩個共享變量進行賦值操作:

a = 1;  b = 2;  

假設當線程A對a進行復制操作的時候發現這個變量在主內存已經被其它的線程加了訪問鎖,那么此時線程A怎么辦?等待釋放鎖?不,等待太浪費時間了,它會去嘗試進行b的賦值操作,b這時候沒被人占用,因此就會先為b賦值,再去為a賦值,那么執行的順序就變成了:

b = 2;  a = 1;  

對于在同一個線程內,這樣的改變是不會對邏輯產生影響的,但是在多線程的情況下指令重排序會帶來問題,看下面這個情景:

在線程A中:

context = loadContext();  inited = true;  

在線程B中:

while(!inited ){   sleep  }   doSomethingwithconfig(context);  

假設A中發生了重排序:

inited = true;  context = loadContext();  

那么B中很可能就會拿到一個尚未初始化或尚未初始化完成的context,從而引發程序錯誤。

想到有一條古老的原則很適合用在這個地方,那就是先要保證程序的正確然后再去優化性能。此處由于重排序產生的錯誤顯然要比重排序帶來的性能優化要重 要的多。要解決重排序問題還是通過volatile關鍵字,volatile關鍵字能確保變量在線程中的操作不會被重排序而是按照代碼中規定的順序進行訪 問。

最后的總結

這篇文章簡單的介紹了Java內存模型、內存可見性和指令重排序。不過最后看來其實主要是在解釋volatile這個關鍵字,個人感覺 volatile關鍵字是Java當中最令人困惑和最難理解的關鍵字。相對于synchronized塊的代碼鎖,volatile應該是提供了一個輕量 級的針對共享變量的鎖,當我們在多個線程間使用共享變量進行通信的時候需要考慮將共享變量用volatile來修飾,對于需要使用volatile的各種 情景,看到IBM Developer Works上有一篇文章總結的很不錯,推薦一下: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

補充說明:64位long和double

在JVM規范中Java內存模型要求lock、unlock、read、load、assign、use、store、write這8個操作必須是 原子的,但是對于64位的long和double來說,如果沒有被volatile修飾符修飾,那么可以不是原子的,注意是可以,即虛擬機在實現的時候可 以選擇是否是原子操作。目前幾乎所有的商用虛擬機都將此實現為原子操作,因此不必每次用到它們都去加volatile修飾。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲a级在线观看| 日韩av中文字幕在线免费观看| 97精品久久久中文字幕免费| 伊人久久久久久久久久久久久| 国模gogo一区二区大胆私拍| 成人女保姆的销魂服务| 日本韩国在线不卡| 在线播放日韩av| 亚洲香蕉成视频在线观看| 亚洲精品午夜精品| 国产精品久久久久久久av电影| 欧美精品videosex牲欧美| 欧美日韩午夜激情| 欧美性一区二区三区| 成人羞羞国产免费| 亚洲精品之草原avav久久| 久久综合色88| 韩国日本不卡在线| 欧美黑人巨大精品一区二区| 欧美日韩国产在线| 亚洲精品美女在线| 国产成人97精品免费看片| 中文字幕v亚洲ⅴv天堂| 亚洲欧美制服第一页| 国产一区二区三区在线视频| 色偷偷av亚洲男人的天堂| 国产精品99久久久久久白浆小说| 国产精品a久久久久久| 欧美激情综合亚洲一二区| 九九久久综合网站| 97香蕉超级碰碰久久免费的优势| 乱亲女秽乱长久久久| 亚洲自拍欧美另类| 全色精品综合影院| 精品av在线播放| 国产精品第七影院| 最近2019中文免费高清视频观看www99| 91高清视频在线免费观看| 青青在线视频一区二区三区| 日韩最新中文字幕电影免费看| 91精品91久久久久久| 中文字幕精品国产| 精品久久香蕉国产线看观看亚洲| 日韩精品中文字幕在线| 日韩成人激情影院| 欧美一级在线亚洲天堂| 亚洲aa中文字幕| 久久久亚洲网站| 神马久久桃色视频| 久久亚洲一区二区三区四区五区高| 91日本在线视频| 91麻豆桃色免费看| 国产精品久久久久久久7电影| 亚洲成人国产精品| 亚洲精品小视频在线观看| 国产精品久久婷婷六月丁香| 成人a级免费视频| 久久精品国产久精国产一老狼| 亚洲国产天堂久久综合网| 国产精品无av码在线观看| 国产视频在线一区二区| 国内精品久久久久久中文字幕| 亚洲精品456在线播放狼人| 久久久噜噜噜久久久| 亚洲欧美综合v| 国产精品美女在线观看| 国产精品久久久久aaaa九色| 国产精品久久91| 日韩在线观看免费| 日韩av123| 97在线观看免费高清| 日韩一区二区三区国产| 亚洲在线观看视频| 国产精品久久久久免费a∨| 国产精品嫩草视频| 久久99久久99精品中文字幕| 日韩精品欧美国产精品忘忧草| 夜夜嗨av色综合久久久综合网| 国产精品视频永久免费播放| 国产精品女人久久久久久| 亚洲男人天堂网| 亚洲香蕉av在线一区二区三区| 日韩欧美在线字幕| 国产亚洲免费的视频看| 成人妇女淫片aaaa视频| 91精品国产综合久久香蕉922| 日韩av网站导航| 久久韩剧网电视剧| 国产精品久久久久久中文字| 亚洲精品国产美女| 中文字幕在线观看亚洲| 国产精品久久久久久久久久东京| 91国内在线视频| 久久久久久久久电影| 欧美大秀在线观看| 欧美精品www在线观看| 26uuu亚洲伊人春色| 亚洲欧美综合另类中字| 色婷婷av一区二区三区在线观看| 国产成人97精品免费看片| 国产精品黄视频| 欧美极品在线播放| 亚洲精品一区二区三区不| 亚洲精品国产精品乱码不99按摩| 欧美三级xxx| 日韩欧美999| 91日本在线视频| 欧美风情在线观看| 欧美最近摘花xxxx摘花| 亚洲自拍另类欧美丝袜| 午夜精品在线视频| 亚洲另类图片色| 久久伊人精品天天| 国产精品久久中文| 日韩中文字幕国产| 久久综合国产精品台湾中文娱乐网| 久久久欧美一区二区| 日韩美女主播视频| 国产成人精品综合久久久| 2019中文字幕在线免费观看| 亚洲欧美中文日韩v在线观看| 日韩av在线免费| 992tv成人免费视频| 国产精品久久久久久久久影视| 亚洲国产美女久久久久| 欧美精品电影在线| 国产国语videosex另类| 成人激情黄色网| 国产欧美日韩中文字幕在线| 亚洲自拍小视频免费观看| 伊人精品在线观看| 亚洲第一福利网站| 精品国产一区二区三区久久久狼| 欧美小视频在线| 久久精品国产电影| 国产女人18毛片水18精品| 色噜噜狠狠狠综合曰曰曰88av| 亚洲国产精品美女| 综合网日日天干夜夜久久| 一区二区三区视频观看| 日韩精品视频免费在线观看| 国内精品视频久久| 性欧美亚洲xxxx乳在线观看| 亚洲欧美日韩精品久久亚洲区| 一区二区在线免费视频| 亚洲欧美激情精品一区二区| 久久久久久中文| 国产成人精品电影久久久| 狠狠色香婷婷久久亚洲精品| 欧美精品在线视频观看| 亚洲天堂男人的天堂| 欧美成人精品在线| 夜夜狂射影院欧美极品| 欧美午夜性色大片在线观看| 亚洲第一视频网| 国产成人精品视频| 精品福利视频导航| 国产精品久久久亚洲| 国产日韩欧美夫妻视频在线观看| 久久久久这里只有精品| 久久人91精品久久久久久不卡| 97国产真实伦对白精彩视频8| 日韩av电影国产| 中文字幕日韩视频|