synchronized鎖升級詳細(xì)過程

前言-對象頭結(jié)構(gòu)

java對象頭由3部分組成:

1、Mark Word

2腺逛、指向類對象(對象的class對象)的指針

3穗椅、數(shù)組長度(數(shù)組類型才有)

重點是 Mark Word結(jié)構(gòu),下面以32位HotSpot為例:

一扒秸、偏向鎖

1昨登、概念:

HotSpot的作者經(jīng)過研究發(fā)現(xiàn)趾代,大多數(shù)情況下,鎖不僅不存在多線程競爭丰辣,而且總是由同一線程多次獲得撒强,為了讓線程獲得鎖的代價更低從而引入偏向鎖。偏向鎖在獲取資源的時候會在鎖對象頭上記錄當(dāng)前線程ID笙什,偏向鎖并不會主動釋放飘哨,這樣每次偏向鎖進(jìn)入的時候都會判斷鎖對象頭中線程ID是否為自己,如果是則不需要進(jìn)行額外的操作得湘,直接進(jìn)入同步操作杖玲。

2顿仇、偏向鎖的獲取過程:

I:判斷是否為可偏向狀態(tài)--MarkWord中鎖標(biāo)志是否為‘01’淘正,是否偏向鎖是否為‘1’

II:如果是可偏向狀態(tài)摆马,則查看線程ID是否為當(dāng)前線程,如果是鸿吆,則進(jìn)入步驟'V'囤采,否則進(jìn)入步驟‘III’

III:通過CAS操作競爭鎖,如果競爭成功惩淳,則將MarkWord中線程ID設(shè)置為當(dāng)前線程ID蕉毯,然后執(zhí)行‘V’;競爭失敗思犁,則執(zhí)行‘IV’

IV:CAS獲取偏向鎖失敗表示有競爭代虾。當(dāng)達(dá)到safepoint時獲得偏向鎖的線程被掛起,偏向鎖升級為輕量級鎖激蹲,然后被阻塞在安全點的線程繼續(xù)往下執(zhí)行同步代碼塊

V:執(zhí)行同步代碼

3棉磨、偏向鎖的撤銷過程:

I:偏向鎖不會主動釋放(撤銷),只有遇到其他線程競爭時才會執(zhí)行撤銷学辱,由于撤銷需要知道當(dāng)前持有該偏向鎖的線程棧狀態(tài)乘瓤,因此要等到safepoint時執(zhí)行,此時持有該偏向鎖的線程(T)有‘II’策泣,‘III’兩種情況衙傀;

II:撤銷----T線程已經(jīng)退出同步代碼塊,或者已經(jīng)不再存活萨咕,則直接撤銷偏向鎖统抬,變成無鎖狀態(tài)----該狀態(tài)達(dá)到閾值20則執(zhí)行批量重偏向

III:升級----T線程還在同步代碼塊中,則將T線程的偏向鎖升級為輕量級鎖危队,當(dāng)前線程執(zhí)行輕量級鎖狀態(tài)下的鎖獲取步驟----該狀態(tài)達(dá)到閾值40則執(zhí)行批量撤銷

4蓄喇、批量重偏向/撤銷:

從‘3、偏向鎖的撤銷過程’可以看出偏向鎖需要等到safepoint才能進(jìn)行鎖升級/撤銷交掏,這種情況偏向鎖不僅不能提高性能妆偏,反而會導(dǎo)致性能下降

思考兩個場景:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? I:線程T1創(chuàng)建了大量對象,并進(jìn)行初始的同步操作盅弛,這時這些對象都偏向T1钱骂;之后線程T2使用這些對象作為鎖進(jìn)行同步操作,則會存在大量的偏向鎖撤銷操作? ? ? ? ? ? ? ? ? ? ? ? II:存在明顯多線程鎖競爭時會存在大量偏向鎖升級過程?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 為了解決這兩個問題挪鹏,jvm提供了批量重偏向/撤銷的機制?

批量重偏向/撤銷過程:??

I:首先引入一個概念epoch见秽,其本質(zhì)是一個時間戳,代表了偏向鎖的有效性讨盒,epoch存儲在可偏向?qū)ο蟮腗arkWord中解取。除了對象中的epoch,對象所屬的類class信息中,也會保存一個epoch值

II:每當(dāng)遇到一個全局安全點時(這里的意思是說批量重偏向沒有完全替代了全局安全點返顺,全局安全點是一直存在的)禀苦,比如要對class C 進(jìn)行批量再偏向蔓肯,則首先對 class C中保存的epoch進(jìn)行增加操作,得到一個新的epoch_new

III:然后掃描所有持有 class C 實例的線程棧振乏,根據(jù)線程棧的信息判斷出該線程是否鎖定了該對象蔗包,僅將epoch_new的值賦給被鎖定的對象中,也就是現(xiàn)在偏向鎖還在被使用的對象才會被賦值epoch_new

IV:退出安全點后慧邮,當(dāng)有線程需要嘗試獲取偏向鎖時调限,直接檢查 class C 中存儲的 epoch 值是否與目標(biāo)對象中存儲的 epoch 值相等, 如果不相等误澳,則說明該對象的偏向鎖已經(jīng)無效了(即用完了耻矮,因為'III'步驟里面已經(jīng)說了只有偏向鎖還在被使用的對象才會有epoch_new,這里不相等的原因是class C里面的epoch值是epoch_new,而當(dāng)前對象的epoch里面的值還是epoch)忆谓,此時競爭線程可以嘗試對此對象重新進(jìn)行偏向操作淘钟,即通過CAS操作將其Mark Word的Thread Id 改成當(dāng)前線程Id

V:當(dāng)epoch達(dá)到重偏向閾值(默認(rèn)20)時,jvm就認(rèn)為該class的偏向鎖偏向的線程有問題陪毡,因此會進(jìn)行批量重偏向米母。當(dāng)epoch達(dá)到批量撤銷閾值(默認(rèn)40)時,jvm就認(rèn)為這個class不再適合偏向鎖毡琉,就會批量撤銷铁瞒,并且在之后的加鎖過程中直接為該class的對象設(shè)置輕量級鎖

二、輕量級鎖

1桅滋、概念:

輕量級鎖是相對于重量級鎖需要阻塞/喚醒涉及上下文切換而言慧耍,主要針對多個線程在不同時間請求同一把鎖的場景。

2丐谋、輕量級鎖獲取過程:

I:進(jìn)行加鎖操作時芍碧,jvm會判斷是否已經(jīng)時重量級鎖,如果不是号俐,則會在當(dāng)前線程棧幀中劃出一塊空間泌豆,作為該鎖的鎖記錄,并且將鎖對象MarkWord復(fù)制到該鎖記錄中

II:復(fù)制成功之后吏饿,jvm使用CAS操作將對象頭MarkWord更新為指向鎖記錄的指針踪危,并將鎖記錄里的owner指針指向?qū)ο箢^的MarkWord。如果成功猪落,則執(zhí)行‘III’贞远,否則執(zhí)行‘IV’

III:更新成功,則當(dāng)前線程持有該對象鎖笨忌,并且對象MarkWord鎖標(biāo)志設(shè)置為‘00’蓝仲,即表示此對象處于輕量級鎖狀態(tài)

IV:更新失敗,jvm先檢查對象MarkWord是否指向當(dāng)前線程棧幀中的鎖記錄,如果是則執(zhí)行‘V’袱结,否則執(zhí)行‘VI’

V:表示鎖重入亮隙;然后當(dāng)前線程棧幀中增加一個鎖記錄第一部分(Displaced Mark Word)為null,并指向Mark Word的鎖對象擎勘,起到一個重入計數(shù)器的作用。

VI:表示該鎖對象已經(jīng)被其他線程搶占颖榜,則進(jìn)行自旋等待(默認(rèn)10次)棚饵,等待次數(shù)達(dá)到閾值仍未獲取到鎖,則升級為重量級鎖

3掩完、輕量級鎖解鎖過程:

I:通過CAS操作把嘗試把線程棧幀中復(fù)制的鎖記錄中的Displaced Mark Word替換當(dāng)前對象頭的MarkWord(即還原對象頭)

II:替換成功則同步塊執(zhí)行順利結(jié)束

III:替換失敗說明已經(jīng)膨脹為重量級鎖噪漾,則在執(zhí)行完同步塊釋放鎖同時喚醒被掛起的線程

4、自適應(yīng)自旋:

根據(jù)以往自旋等待時是否能夠獲得鎖且蓬,來動態(tài)調(diào)整自旋的時間(循環(huán)數(shù)目)

三欣硼、重量級鎖

1、重量級鎖加鎖過程:

I:調(diào)用omAlloc分配一個ObjectMonitor對象恶阴,把Mark Word鎖標(biāo)志置為‘10’诈胜,然后Mark Word存儲指向ObjectMonitor對象的指針。ObjectMonitor對象有兩個隊列和一個指針冯事,每個需要獲取鎖的線程都包裝成ObjectWaiter對象

II:多個線程同時執(zhí)行同一段同步代碼時焦匈,ObjectWaiter先進(jìn)入_EntryList隊列,當(dāng)某個線程獲取到對象的monitor以后進(jìn)入_Owner區(qū)域昵仅,并把monitor中的owner變量設(shè)置為當(dāng)前線程同時monitor中的計數(shù)器count+1缓熟;

2、重量級鎖釋放過程:

I:若同步塊中的線程調(diào)用wait()方法摔笤,則釋放持有的monitor够滑,owner遍歷置為null,count-1吕世,同時線程進(jìn)入_WaitSet等待被喚醒

II:若當(dāng)前同步塊執(zhí)行完畢彰触,則也釋放持有的monitor,owner遍歷置為null命辖,count-1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渴析,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吮龄,更是在濱河造成了極大的恐慌俭茧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漓帚,死亡現(xiàn)場離奇詭異母债,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門毡们,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迅皇,“玉大人,你說我怎么就攤上這事衙熔〉峭牵” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵红氯,是天一觀的道長框咙。 經(jīng)常有香客問我,道長痢甘,這世上最難降的妖魔是什么喇嘱? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮塞栅,結(jié)果婚禮上者铜,老公的妹妹穿的比我還像新娘。我一直安慰自己放椰,他們只是感情好作烟,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著砾医,像睡著了一般俗壹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上藻烤,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天绷雏,我揣著相機與錄音,去河邊找鬼怖亭。 笑死涎显,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兴猩。 我是一名探鬼主播期吓,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倾芝!你這毒婦竟也來了讨勤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晨另,失蹤者是張志新(化名)和其女友劉穎潭千,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體借尿,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡刨晴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年屉来,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狈癞。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡茄靠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝶桶,到底是詐尸還是另有隱情慨绳,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布真竖,位于F島的核電站脐雪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疼邀。R本人自食惡果不足惜喂江,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一召锈、第九天 我趴在偏房一處隱蔽的房頂上張望旁振。 院中可真熱鬧,春花似錦涨岁、人聲如沸拐袜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹬铺。三九已至,卻和暖如春秉撇,著一層夾襖步出監(jiān)牢的瞬間甜攀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工琐馆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留规阀,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓瘦麸,卻偏偏與公主長得像谁撼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子滋饲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355