java高效并發(fā)學(xué)習(xí)筆記(一)java內(nèi)存模型

java高效并發(fā)學(xué)習(xí)筆記(一)java內(nèi)存模型

學(xué)習(xí)JVM+JAVA多線程中宋雏,學(xué)習(xí)的書籍是《深入理解java虛擬機》——周志明

這里記錄一些筆記以便日后經(jīng)常學(xué)習(xí)回顧。

學(xué)習(xí)java虛擬機的并發(fā)之前,了解了物理計算機中并發(fā)的一些處理情況剪芍。計算機在處理運算任務(wù)的時候加入了高速緩存來調(diào)和處理器以及內(nèi)存之間不同數(shù)量級導(dǎo)致的耗時問題:將需要運算的數(shù)據(jù)復(fù)制到緩存中,然后進行高速運算,之后再由緩存同步回內(nèi)存中惩嘉。在java虛擬機中,定義了一種java內(nèi)存模型踢故,可以類比物理計算機的這種處理方式文黎。

主內(nèi)存與工作內(nèi)存

java虛擬機的內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中惹苗,線程對變量的操作都必須在工作內(nèi)存中進行,而不能直接讀寫主內(nèi)存中的變量耸峭。不同線程不能訪問對方的工作內(nèi)存桩蓉。

內(nèi)存之間的交互操作

根據(jù)上面所說,線程操作都是在工作內(nèi)存中劳闹,所以就存在主內(nèi)存和工作內(nèi)存之間的操作情況院究,也就是說一個變量怎么才能從主內(nèi)存中拷貝到工作內(nèi)存中,而工作內(nèi)存中的變量在線程操作完之后又是怎么寫回主內(nèi)存的本涕。java內(nèi)存模型規(guī)定了8中操作來完成上述的情況业汰,而且這8中操作都是原子性的。

lock(鎖定):作用于主內(nèi)存的變量偏友,它將一個變量標識為一條線程獨占的狀態(tài)蔬胯。

unlock(解鎖):作用于主內(nèi)存的變量,它將一個處于鎖定狀態(tài)的變量釋放出來位他,釋放后的變量才可以被其他線程鎖定氛濒。

read(讀取):作用于主內(nèi)存的變量鹅髓,它把一個變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存舞竿,以便之后的load動作使用。

load(載入):作用于工作內(nèi)存的變量窿冯,它把read動作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中骗奖。

use(使用):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個變量的值傳遞給執(zhí)行引擎醒串,每當虛擬機遇到一個需要使用到變量的值的字節(jié)碼指令時將會執(zhí)行操作执桌。

assign(賦值):作用于工作內(nèi)存的變量,它把一個從執(zhí)行引擎接收到的值賦給工作內(nèi)存的變量芜赌,每當虛擬機遇到一個給變量賦值的字節(jié)碼指令時執(zhí)行這個操作仰挣。

store(存儲):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個變量的值傳送到主內(nèi)存中缠沈,以便隨后的write動作膘壶。

write(寫入):作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中得到的變量的值放入主內(nèi)存的變量中洲愤。

以上8個操作是內(nèi)存模型規(guī)定的基本操作颓芭,其中read與load、store與write是成對出現(xiàn)的柬赐。

當一個線程對某一變量進行操作時亡问,如果此時有其他線程需要得到該變量的值,那么在上一線程沒有將變量同步回主內(nèi)存中時肛宋,此時后一線程所得到的該變量的值就是不確定的玛界,于是就有了volatile万矾。

volatile

volatile是java虛擬機提供的最輕量級的同步機制,該關(guān)鍵字實現(xiàn)了兩個功能:保證被修飾變量對所有線程的可見性慎框;禁止指令重排序優(yōu)化。

書中有詳細的解釋后添,這里就寫一些簡單的筆記記錄吧笨枯。

首先對于可見性的理解,volatile的可見性無法保證原子性遇西,在一下兩種情況下可以使用:運算結(jié)果并不依賴變量的當前值馅精,或者能夠保證只有單一的線程修改變量的值;變量不需要與其他的狀態(tài)變量共同參與不變約束粱檀。

對于禁止指令重排序的理解洲敢,指令重排序是指CPU可以不按照程序規(guī)定的順序?qū)⒍鄺l指令分發(fā)給相應(yīng)的電路單元處理。

原子性茄蚯、可見性压彭、有序性

關(guān)于這些特性,需要了解那些操作實現(xiàn)了這3種特性渗常。

原子性:java內(nèi)存模型的操作保證了原子性壮不。當然lock與unlock提供了更大范圍的原子性,反映到j(luò)ava代碼中就是同步塊——synchronized關(guān)鍵字皱碘。

可見性:可見性就是當一個線程修改了共享變量的值询一,其他線程能夠立刻得知這個修改。volatile就實現(xiàn)了可見性癌椿,當然實現(xiàn)了可見性的還有synchronized和final健蕊。synchronized的原理是因為執(zhí)行unlock之前必須將變量同步回主內(nèi)存。而final的原理是被修飾的字段在構(gòu)造器中一旦初始化完成踢俄,并且構(gòu)造器沒有把this的引用傳遞出去缩功,那么在其他線程中就能看到final字段的值。

有序性:在本線程中褪贵,所有的操作都是有序的掂之;在一個線程中觀察另一個線程,所有的操作都是無序的脆丁。而實現(xiàn)有序操作的方法有volatile和synchronized世舰。volatile是由于其禁止指令重排序,synchronized是因為一個變量在同一時刻只允許一條線程對其進行l(wèi)ock操作槽卫。

先行先發(fā)原則

在判斷數(shù)據(jù)是否存在競爭跟压、線程是否安全中,主要依靠了這個原則歼培。

先行先發(fā)原則是java內(nèi)存模型中定義的兩項操作之間的偏序關(guān)系震蒋,如果說操作A先行發(fā)生于B茸塞,其實就是說發(fā)生操作B之前,操作A產(chǎn)生的影響能被B觀察到查剖。比如:

i=1;

j=i;

i=2;

假設(shè)線程A中的操作i=1先行發(fā)生于線程B中的操作j=i钾虐,那么可以確定線程B的操作之后j的值一定等于1。現(xiàn)在加入C線程笋庄,依然保持線程A和線程B之間的先行發(fā)生關(guān)系效扫,而線程C出現(xiàn)在線程A和線程B操作之間,但是線程C與線程B沒有先行發(fā)生關(guān)系直砂,那么j的值是多少呢菌仁?答案不確定,可能是1也可能是2静暂,因為線程C的操作對于線程B來說可以被觀察到济丘,也可能不會。這種情況便需要保證同步洽蛀,因為不具備多線程的安全性摹迷。(時間先后順序與先行發(fā)生原則之間基本沒有太大關(guān)系,所以在衡量并發(fā)安全問題的時候不要受到時間順序的干擾辱士,一切必須以先行發(fā)生原則為準泪掀。)

java內(nèi)存模型下有一些先行發(fā)生關(guān)系,無需任何的同步器協(xié)助就可以直接使用颂碘。如果兩個操作時間關(guān)系不在此列异赫,并且無法從下列規(guī)則推導(dǎo)出來的話,它們就沒有順序性保障头岔。

程序次序規(guī)則:在一個線程內(nèi)塔拳,按照程序代碼順序,寫在前面的操作先行發(fā)生與寫在后面的操作峡竣。

管理鎖定規(guī)則:一個unlock操作先行發(fā)生與后面對同一個鎖的lock操作靠抑。

線程啟動規(guī)則:Thread對象的start()方法先行發(fā)生于此線程的每一個動作。

線程終止規(guī)則:線程中所有操作都先行于對此線程的終止檢測适掰,我們可以通過Thread.join()方法結(jié)束颂碧、Thread.isAlive()的返回值等手段檢測到線程已經(jīng)終止執(zhí)行。

線程終端規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生类浪。

對象終結(jié)規(guī)則:一個對象的初始化完成先行發(fā)生于它的finalize()方法的開始载城。

volatile變量規(guī)則:對一個volatile變量的寫操作先行發(fā)生于后面對這個變量的讀操作。

傳遞性:A先行發(fā)生于B费就,B先行發(fā)生于C诉瓦,則A先行發(fā)生與C。

發(fā)布于 2017-08-16

著作權(quán)歸作者所有

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市睬澡,隨后出現(xiàn)的幾起案子固额,更是在濱河造成了極大的恐慌,老刑警劉巖煞聪,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斗躏,死亡現(xiàn)場離奇詭異,居然都是意外死亡米绕,警方通過查閱死者的電腦和手機瑟捣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅干,“玉大人,你說我怎么就攤上這事捐祠〖盍郏” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵踱蛀,是天一觀的道長窿给。 經(jīng)常有香客問我,道長率拒,這世上最難降的妖魔是什么崩泡? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮猬膨,結(jié)果婚禮上角撞,老公的妹妹穿的比我還像新娘。我一直安慰自己勃痴,他們只是感情好谒所,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沛申,像睡著了一般劣领。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铁材,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天尖淘,我揣著相機與錄音,去河邊找鬼著觉。 笑死村生,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的固惯。 我是一名探鬼主播梆造,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镇辉?” 一聲冷哼從身側(cè)響起屡穗,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忽肛,沒想到半個月后村砂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡屹逛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年础废,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罕模。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡评腺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淑掌,到底是詐尸還是另有隱情蒿讥,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布抛腕,位于F島的核電站芋绸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏担敌。R本人自食惡果不足惜摔敛,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望全封。 院中可真熱鬧马昙,春花似錦、人聲如沸售貌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颂跨。三九已至敢伸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恒削,已是汗流浹背池颈。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钓丰,地道東北人躯砰。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像携丁,于是被迫代替她去往敵國和親琢歇。 傳聞我的和親對象是個殘疾皇子兰怠,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Java內(nèi)存模型與線程 Java內(nèi)存模型 主內(nèi)存與工作內(nèi)存 Java內(nèi)存模型的主要目標是定義程序中各個變量的訪問規(guī)...
    碼夢的一生閱讀 482評論 0 9
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司李茫,掛了不少揭保,但最終還是拿到小米、百度魄宏、阿里秸侣、京東、新浪宠互、CVTE味榛、樂視家的研發(fā)崗...
    時芥藍閱讀 42,274評論 11 349
  • 說的是閩南人的中秋節(jié),其隆重程度大大過于春節(jié)予跌,主要是因為博餅文化的源遠流長搏色,成了如今閩南地區(qū)獨具特色的民間...
    天行健與地勢坤閱讀 536評論 0 0
  • 一天小歪獸去昆侖山找沙棠吃,在一個洞口發(fā)現(xiàn)了一株大得出奇沙棠券册,然后小歪屁顛屁顛的跑過去了继榆。等它走近時突然被某種不知...
    歪小獸閱讀 111評論 0 0
  • 萬萬沒想到,時隔一年我開始回憶這一場沙漠少女們的奇遇記汁掠,可能是我想一直和你們待在一塊吧,在哪都行集币,在路上更好考阱。 大...
    洛嘉桃子閱讀 413評論 0 1