JMM簡(jiǎn)介

Java Memory Model(JMM)java內(nèi)存模型,區(qū)別與java內(nèi)存結(jié)構(gòu)。JMM定義了一套在多線程讀寫(xiě)共享數(shù)據(jù)(變量享郊、數(shù)組)時(shí),對(duì)數(shù)據(jù)的可見(jiàn)性孝鹊、有序性和原子性的規(guī)則和保障炊琉。

原子性

原子性是指一個(gè)操作是不可中斷的,要么全部執(zhí)行成功要么全部執(zhí)行失敗又活。即使在多個(gè)線程一起執(zhí)行的時(shí)候苔咪,一個(gè)操作一旦開(kāi)始,就不會(huì)被其他線程所干擾柳骄。
多線程情況下团赏,對(duì)同一個(gè)對(duì)象進(jìn)行操作時(shí),會(huì)導(dǎo)致字節(jié)碼指令交錯(cuò)執(zhí)行耐薯,從而產(chǎn)生原子性問(wèn)題舔清,可以通過(guò)synchronize關(guān)鍵字解決

可見(jiàn)性

可見(jiàn)性是指當(dāng)一個(gè)線程修改了共享變量后隘世,其他線程能夠立即得知這個(gè)修改

有序性

如果在本線程內(nèi)觀察,所有的操作都是有序的鸠踪;(線程內(nèi)表現(xiàn)為串行的語(yǔ)義)如果在一個(gè)線程中觀察另外一個(gè)線程丙者,所有的操作都是無(wú)序的。
多線程情況下营密,jvm會(huì)進(jìn)行指令重排械媒,會(huì)影響有序性。


happens-before

happens-before規(guī)定了哪些寫(xiě)操作對(duì)其他讀操作可見(jiàn)评汰,即前一個(gè)操作的結(jié)果可以被后續(xù)的操作獲取纷捞。它是可見(jiàn)性與有序性的一套規(guī)則總結(jié)。
程序次序規(guī)則:在一個(gè)線程內(nèi)一段代碼的執(zhí)行結(jié)果是有序的被去。就是還會(huì)指令重排主儡,但是隨便它怎么排,結(jié)果是按照我們代碼的順序生成的不會(huì)變惨缆!

管程鎖定規(guī)則:就是無(wú)論是在單線程環(huán)境還是多線程環(huán)境糜值,對(duì)于同一個(gè)鎖來(lái)說(shuō),一個(gè)線程對(duì)這個(gè)鎖解鎖之后坯墨,另一個(gè)線程獲取了這個(gè)鎖都能看到前一個(gè)線程的操作結(jié)果寂汇!(管程是一種通用的同步原語(yǔ),synchronized就是管程的實(shí)現(xiàn))

volatile變量規(guī)則:就是如果一個(gè)線程先去寫(xiě)一個(gè)volatile變量捣染,然后一個(gè)線程去讀這個(gè)變量骄瓣,那么這個(gè)寫(xiě)操作的結(jié)果一定對(duì)讀的這個(gè)線程可見(jiàn)。

線程啟動(dòng)規(guī)則:在主線程A執(zhí)行過(guò)程中耍攘,啟動(dòng)子線程B榕栏,那么線程A在啟動(dòng)子線程B之前對(duì)共享變量的修改結(jié)果對(duì)線程B可見(jiàn)。

線程終止規(guī)則:在主線程A執(zhí)行過(guò)程中蕾各,子線程B終止扒磁,那么線程B在終止之前對(duì)共享變量的修改結(jié)果在線程A中可見(jiàn)。

線程中斷規(guī)則:對(duì)線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程代碼檢測(cè)到中斷事件的發(fā)生示损,可以通過(guò)Thread.interrupted()檢測(cè)到是否發(fā)生中斷渗磅。

傳遞規(guī)則:這個(gè)簡(jiǎn)單的嚷硫,就是happens-before原則具有傳遞性检访,即A happens-before B , B happens-before C仔掸,那么A happens-before C脆贵。

對(duì)象終結(jié)規(guī)則:這個(gè)也簡(jiǎn)單的,就是一個(gè)對(duì)象的初始化的完成起暮,也就是構(gòu)造函數(shù)執(zhí)行的結(jié)束一定 happens-before它的finalize()方法卖氨。


synchronize和volatile對(duì)比

1、volatile是線程同步的輕量級(jí)實(shí)現(xiàn),性能比synchronize好
2筒捺、volatile只能修飾變量柏腻,而synchronize可以修飾方法、代碼塊和變量
3系吭、volatile多線程時(shí)不會(huì)發(fā)生阻塞五嫂,而synchronize會(huì)阻塞線程
4、volatile可以保證可見(jiàn)性和有序性(禁止指令重排)肯尺,無(wú)法保證原子性沃缘,而synchronize都可以保證
總結(jié):volatile就是保證變量對(duì)其他線程的可見(jiàn)性和防止指令重排序
而synchronize解決多個(gè)線程訪問(wèn)資源的同步性


鎖狀態(tài)

鎖的狀態(tài)總共有四種:
無(wú)鎖狀態(tài)(01)、偏向鎖(01)则吟、輕量級(jí)鎖(00)和重量級(jí)鎖(10)槐臀。
隨著鎖的競(jìng)爭(zhēng),鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖氓仲,再升級(jí)的重量級(jí)鎖(但是鎖的升級(jí)是單向的水慨,也就是說(shuō)只能從低到高升級(jí),不會(huì)出現(xiàn)鎖的降級(jí))


CAS和原子類(lèi)

CAS即Compare and Swap敬扛,是一種樂(lè)觀鎖的思想讥巡。為了保證該變量的可見(jiàn)性,需要使用volatile修飾舔哪,結(jié)合CAS和volatile可以實(shí)現(xiàn)無(wú)鎖并發(fā)欢顷,適用于競(jìng)爭(zhēng)不激烈、多核CPU的場(chǎng)景捉蚤。
原子操作類(lèi):AtomicInteger抬驴、AtomicBoolean,底層采用CAS+volatile實(shí)現(xiàn)缆巧。


Monitor

每一個(gè)java對(duì)象都會(huì)關(guān)聯(lián)一個(gè)monitor對(duì)象布持,monitor對(duì)象的主要組成部分:waitSet(之前獲得過(guò)鎖的線程,條件不滿足后會(huì)進(jìn)入)陕悬,EntryList(線程等待隊(duì)列)题暖,Owner(鎖持有者)。

synchronized重量級(jí)鎖

基于悲觀鎖思想捉超,加鎖后關(guān)聯(lián)monitor對(duì)象胧卤,線程進(jìn)入后成為monitor的owner(即owner指向該線程),當(dāng)其他線程訪問(wèn)時(shí)會(huì)先檢查monitor對(duì)象是否空閑拼岳,若monitor對(duì)象已經(jīng)被持有枝誊,則進(jìn)入entryList等待,從而實(shí)現(xiàn)阻塞惜纸。

synchronized輕量級(jí)鎖

如果多線程訪問(wèn)一個(gè)對(duì)象的時(shí)間是錯(cuò)開(kāi)的叶撒,則可以使用輕量級(jí)鎖來(lái)優(yōu)化绝骚。

加鎖過(guò)程:如果加鎖對(duì)象為無(wú)鎖狀態(tài)(01)時(shí),線程首先會(huì)在棧幀中創(chuàng)建一個(gè)鎖記錄空間(Lock Record)祠够,用于存儲(chǔ)鎖對(duì)象的Mark Work压汪,并將使用CAS操作鎖對(duì)象的Mark Work更新為指向鎖記錄的指針且將鎖記錄里的owner指針指向鎖對(duì)象的Mark Work,此時(shí)鎖對(duì)象的鎖標(biāo)志位是00(輕量級(jí)鎖)古瓤,如果更新失敗蛾魄,jvm首先會(huì)檢查鎖對(duì)象的Mark work是否指向當(dāng)前線程的棧幀,是的話就進(jìn)行鎖重入湿滓,繼續(xù)執(zhí)行同步代碼滴须,否則說(shuō)明多線程競(jìng)爭(zhēng)鎖,輕量級(jí)鎖就要升級(jí)為重量級(jí)鎖叽奥。

解鎖過(guò)程:通過(guò)CAS操作嘗試把線程中的Mark word 替換當(dāng)前對(duì)象的Mark word扔水,若操作成功則解鎖完成,否則說(shuō)明鎖已經(jīng)膨脹為重量級(jí)鎖朝氓,那就要在釋放鎖的同時(shí)喚醒被掛起的線程魔市。

鎖膨脹

鎖膨脹是指輕量級(jí)鎖在出現(xiàn)競(jìng)爭(zhēng)的情況下,當(dāng)線程1持有輕量鎖時(shí)赵哲,線程2過(guò)來(lái)競(jìng)爭(zhēng)的時(shí)候待德,輕量鎖會(huì)膨脹為重量鎖,線程2會(huì)進(jìn)入等待隊(duì)列(EntryList)枫夺。

鎖自旋

重量級(jí)鎖競(jìng)爭(zhēng)的時(shí)候将宪,不一定馬上進(jìn)入阻塞,還可以使用自旋來(lái)進(jìn)行優(yōu)化橡庞,如果當(dāng)前線程自旋成功较坛,就避免了阻塞。

  • java6之后自旋鎖是自適應(yīng)的扒最,若自旋成功過(guò)丑勤,下次就會(huì)多自旋幾次;反之吧趣,就少自旋或不自旋
  • 自旋會(huì)占用CPU時(shí)間法竞,單核CPU自旋就是浪費(fèi),多核CPU才能發(fā)揮優(yōu)勢(shì)
  • java7之后不能控制是否開(kāi)啟自旋功能

偏向鎖

引入偏向鎖是為了在無(wú)多線程競(jìng)爭(zhēng)的情況下盡量減少不必要的輕量級(jí)鎖執(zhí)行路徑(即減少鎖重入)强挫,因?yàn)檩p量級(jí)鎖的獲取及釋放依賴(lài)多次CAS原子指令岔霸,而偏向鎖只需要在置換ThreadID的時(shí)候依賴(lài)一次CAS原子指令(由于一旦出現(xiàn)多線程競(jìng)爭(zhēng)的情況就必須撤銷(xiāo)偏向鎖,所以偏向鎖的撤銷(xiāo)操作的性能損耗必須小于節(jié)省下來(lái)的CAS原子指令的性能消耗)纠拔。

偏向鎖:只有第一次使用CAS時(shí)將線程ID設(shè)置到對(duì)象的Mark Work頭秉剑,之后發(fā)現(xiàn)這個(gè)線程ID是自己的就表示沒(méi)有競(jìng)爭(zhēng)泛豪,不用重新CAS稠诲。

一個(gè)對(duì)象創(chuàng)建時(shí)默認(rèn)開(kāi)啟偏向鎖侦鹏,但該默認(rèn)是延遲的(可通過(guò)VM參數(shù)BiasedLockingStartupDelay=0來(lái)禁用延遲),不會(huì)在程序啟動(dòng)時(shí)立即生效臀叙。

  • 輕量級(jí)鎖是為了在線程交替執(zhí)行同步塊時(shí)提高性能略水,而偏向鎖則是在只有一個(gè)線程執(zhí)行同步塊時(shí)進(jìn)一步提高性能。

偏向鎖撤銷(xiāo)

  • 對(duì)象調(diào)用hashCode()方法會(huì)禁用該對(duì)象的偏向鎖劝萤,原因就是調(diào)用了hashCode()方法渊涝,對(duì)象頭就沒(méi)有地方存放線程id了,只能禁用該對(duì)象的偏向鎖床嫌。重量級(jí)鎖在monitor對(duì)象中存儲(chǔ)hashCode跨释。
  • 當(dāng)兩個(gè)及以上線程使用同一個(gè)對(duì)象時(shí),偏向鎖將會(huì)升級(jí)為輕量級(jí)鎖厌处,如果這些線程會(huì)產(chǎn)生資源競(jìng)爭(zhēng)鳖谈,則進(jìn)一步升級(jí)為重量級(jí)鎖。
  • 對(duì)象調(diào)用wait/notify阔涉,也會(huì)撤銷(xiāo)對(duì)象的偏向狀態(tài)缆娃,原因是只有重量級(jí)鎖才會(huì)有wait/notify機(jī)制
  • 連續(xù)撤銷(xiāo)偏向超過(guò)40 次(超過(guò)閾值),jvm會(huì)認(rèn)為確實(shí)偏向錯(cuò)了瑰排,于是所有類(lèi)都不可偏向贯要,新建的對(duì)象也不可以偏向

批量重偏向

如果對(duì)象雖然被多個(gè)線程訪問(wèn),但沒(méi)有競(jìng)爭(zhēng)椭住,這時(shí)偏向了線程 T1 的對(duì)象仍有機(jī)會(huì)重新偏向 T2崇渗,重偏向會(huì)重置對(duì)象的 Thread ID;當(dāng)撤銷(xiāo)偏向鎖達(dá)到閾值 20 次后京郑,jvm 會(huì)這樣覺(jué)得显押,我是不是偏向錯(cuò)了呢,于是會(huì)在給這些對(duì)象加鎖時(shí)重新偏向至t2傻挂。因?yàn)榍?9次是輕量乘碑,釋放之后為無(wú)鎖不可偏向,但是20次后面的是偏向t2金拒,釋放之后依然是偏向t2兽肤。

鎖消除

JIT即時(shí)編譯器對(duì)字節(jié)碼做的優(yōu)化,當(dāng)判斷加鎖對(duì)象線程安全時(shí)绪抛,會(huì)進(jìn)行鎖消除资铡。

鎖粗化

JIT即時(shí)編譯器對(duì)字節(jié)碼做的優(yōu)化,當(dāng)發(fā)現(xiàn)相鄰的synchronize塊使用的是同一個(gè)鎖對(duì)象幢码,那么就會(huì)把這幾個(gè)synchronize塊合并為一個(gè)加大的同步塊笤休,避免頻繁申請(qǐng)和釋放鎖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末症副,一起剝皮案震驚了整個(gè)濱河市店雅,隨后出現(xiàn)的幾起案子政基,更是在濱河造成了極大的恐慌,老刑警劉巖闹啦,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沮明,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡窍奋,警方通過(guò)查閱死者的電腦和手機(jī)荐健,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)琳袄,“玉大人江场,你說(shuō)我怎么就攤上這事〗讯海” “怎么了扛稽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)滑负。 經(jīng)常有香客問(wèn)我在张,道長(zhǎng),這世上最難降的妖魔是什么矮慕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任帮匾,我火速辦了婚禮,結(jié)果婚禮上痴鳄,老公的妹妹穿的比我還像新娘瘟斜。我一直安慰自己,他們只是感情好痪寻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布螺句。 她就那樣靜靜地躺著,像睡著了一般橡类。 火紅的嫁衣襯著肌膚如雪蛇尚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天顾画,我揣著相機(jī)與錄音取劫,去河邊找鬼。 笑死研侣,一個(gè)胖子當(dāng)著我的面吹牛谱邪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庶诡,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼惦银,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扯俱,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤书蚪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蘸吓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體善炫,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撩幽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年库继,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窜醉。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宪萄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榨惰,到底是詐尸還是另有隱情拜英,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布琅催,位于F島的核電站居凶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏藤抡。R本人自食惡果不足惜侠碧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缠黍。 院中可真熱鬧弄兜,春花似錦、人聲如沸瓷式。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贸典。三九已至视卢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間廊驼,已是汗流浹背腾夯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔬充,地道東北人蝶俱。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饥漫,于是被迫代替她去往敵國(guó)和親榨呆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

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