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

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

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

2019-11-11 04:21:37
字體:
來源:轉載
供稿:網友

并發本來就是個有意思的問題,尤其是現在又流行這么一句話:“高帥富加機器,窮矮搓搞優化”。從這句話可以看到,無論是高帥富還是窮矮搓都需要深入理解并發編程,高帥富加多了機器,需要協調多臺機器或者多個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
成人性生交大片免费看视频直播| 久久久亚洲精选| 成人免费视频xnxx.com| 成人精品久久一区二区三区| 在线丨暗呦小u女国产精品| 亚洲日本欧美日韩高观看| 一区二区三区国产在线观看| 国产精品中文字幕在线| 播播国产欧美激情| 亚洲在线视频观看| 欧美黑人性猛交| 91在线视频导航| 日韩禁在线播放| 国产69精品久久久久久| 国产精品你懂得| 在线精品高清中文字幕| 91国产视频在线| 国产精品网站大全| 97国产在线观看| 亚洲国产精品久久精品怡红院| 久久久免费在线观看| 欧美激情综合亚洲一二区| 久久大大胆人体| 久久躁日日躁aaaaxxxx| 揄拍成人国产精品视频| 日韩影视在线观看| 亚洲影院污污.| 国产精品美女久久久久av超清| 成人网在线免费观看| 欧美激情在线有限公司| 国产精品入口免费视| 色诱女教师一区二区三区| 欧美在线视频观看免费网站| 欧美精品在线免费播放| 国产91亚洲精品| 国产精品久久久久久一区二区| 久久亚洲欧美日韩精品专区| 最近2019好看的中文字幕免费| 国产精品国产亚洲伊人久久| 亚洲欧美国产va在线影院| 亚洲一区www| 91久久久久久久一区二区| 欧美精品一二区| 4438全国亚洲精品在线观看视频| 欧美最顶级的aⅴ艳星| 欧美夫妻性生活视频| 成人欧美一区二区三区黑人| 在线观看日韩欧美| 在线激情影院一区| 91精品视频在线| 久久久久久91| zzijzzij亚洲日本成熟少妇| 日韩不卡中文字幕| 国产成人亚洲综合| 久久躁狠狠躁夜夜爽| 欧美主播福利视频| 国产精品久久久久久久久久小说| 日韩av色在线| 38少妇精品导航| 国产一区二区精品丝袜| 色在人av网站天堂精品| 亚洲最大激情中文字幕| 日本道色综合久久影院| 国产热re99久久6国产精品| 亚洲美女免费精品视频在线观看| 91av国产在线| www.欧美精品一二三区| 欧美日韩美女视频| 中日韩美女免费视频网站在线观看| 亚洲综合一区二区不卡| 91久久久久久| 欧美日韩综合视频| 一区二区三区www| 亚洲成人av在线播放| 国产精品吹潮在线观看| 久久成人人人人精品欧| 亚洲一区二区三区xxx视频| 国产91成人在在线播放| 中文字幕亚洲欧美一区二区三区| 成人久久一区二区三区| 欧美成aaa人片免费看| 成人乱人伦精品视频在线观看| 国产精品精品一区二区三区午夜版| 国产激情久久久| 午夜精品久久久久久99热软件| 欧美成人免费在线视频| 亚洲片在线观看| 国产91精品黑色丝袜高跟鞋| 国内精品美女av在线播放| 国产精品福利无圣光在线一区| 午夜精品理论片| 亚洲片在线资源| 日韩最新免费不卡| 午夜精品理论片| 亚洲精品成a人在线观看| 色综合天天综合网国产成人网| 欧美在线视频观看免费网站| 欧美中文字幕在线观看| 成人黄色短视频在线观看| 国产精品91视频| 日韩成人黄色av| 成人女保姆的销魂服务| 在线观看亚洲视频| 色综合久久天天综线观看| 黄色一区二区三区| 91国内免费在线视频| 色综合伊人色综合网站| 国产精品一区二区久久| 国产精品极品在线| 欧美日本中文字幕| 久久国产精品久久久久久久久久| 永久免费看mv网站入口亚洲| 亚洲性生活视频在线观看| 亚洲а∨天堂久久精品9966| 国产精品久久久久久久av电影| 91久久精品美女高潮| 国色天香2019中文字幕在线观看| 欧美亚洲在线视频| 91精品视频大全| 色婷婷亚洲mv天堂mv在影片| 午夜精品福利在线观看| 伊人激情综合网| 亚洲人成电影在线| 国产欧美精品xxxx另类| 91精品国产九九九久久久亚洲| 国产亚洲在线播放| 国产精品69久久久久| 97视频在线观看成人| 97国产suv精品一区二区62| 久久久久在线观看| 欧美中文字幕在线播放| 久久天天躁狠狠躁夜夜爽蜜月| 欧美日韩国产成人在线观看| 亚洲免费电影一区| 久久久久久久电影一区| 91九色综合久久| 久久久www成人免费精品| 精品亚洲aⅴ在线观看| 性日韩欧美在线视频| 日本电影亚洲天堂| 国产欧美日韩中文字幕在线| 欧美亚洲日本网站| 精品中文字幕在线观看| 色先锋久久影院av| 精品自拍视频在线观看| 欧美视频一区二区三区…| 欧美激情久久久久久| 高清欧美电影在线| 性色av一区二区咪爱| 黄网动漫久久久| 国产午夜精品全部视频播放| 亚洲精品中文字幕av| 91高潮精品免费porn| 国产日本欧美视频| 日韩中文字幕在线精品| 成人天堂噜噜噜| 国产一区二区三区网站| 日韩精品在线免费| 国产精品av网站| 色偷偷av亚洲男人的天堂| 日韩中文字幕免费看| 色综合色综合久久综合频道88| 亚洲奶大毛多的老太婆| 日韩欧美亚洲范冰冰与中字|