synchronized實(shí)現(xiàn)及鎖膨脹

首先介紹關(guān)于synchronized的一些基礎(chǔ)知識(shí)邢羔。

作用于實(shí)例他去、方法、Class上的效果有什么不同

實(shí)例

        Object lock = new Object();

        synchronized (lock) {
            doSomething();
        }

synchronized作用于實(shí)例時(shí)柱锹,是怎么實(shí)現(xiàn)鎖的功能的呢哪自?

通過查看字節(jié)碼指令我們可以發(fā)現(xiàn)monitorentermonitorexit兩個(gè)指令,這兩個(gè)指令就是通過Monitor來進(jìn)行獲取鎖釋放鎖的指令禁熏。

      11: monitorenter
      12: invokestatic  #3                  // Method doSomething:()V
      15: aload_2
      16: monitorexit

方法

    public synchronized void doSomething(){
    }
  public synchronized void doSomething();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED //看這里
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 11: 0

通過字節(jié)碼可以看到壤巷,doSomething()方法在常量池中的method_info中被標(biāo)記為ACC_SYNCHRONIZED,當(dāng)線程訪問方法時(shí)會(huì)檢查是否存在該標(biāo)記瞧毙,如果存在胧华,則需要獲取Monitor對(duì)象,再通過Monitor的enter和exit來進(jìn)行獲取鎖釋放鎖的操作升筏。

Class

        synchronized (Test.class) {
        }
        7: goto          15
       10: astore_2
       11: aload_1
       12: monitorexit

根據(jù)字節(jié)碼指令可以看到撑柔,實(shí)現(xiàn)鎖的方式與作用于對(duì)象實(shí)例時(shí)相同,也是通過monitorentermonitorexit兩個(gè)指令來實(shí)現(xiàn)的鎖您访。不同于實(shí)例的地方是铅忿,作用于Class時(shí),鎖的對(duì)象是Class對(duì)象的實(shí)例灵汪。

Monitor

前文中提到的monitorentermonitorexit檀训,以及Monitor,都是什么呢享言?

Monitor是鎖的概念峻凫,在Hotspot虛擬機(jī)中它是由ObjectMonitor來實(shí)現(xiàn)的,我們的字節(jié)碼指令 monitorentermonitorexit览露,也都是由該對(duì)象來實(shí)現(xiàn)荧琼。如果還有希望更深入研究的同學(xué),可以去翻閱Hotspot的源碼差牛,這部分在ObjectMonitor文件中可以找到命锄。

ObjectMonitor(){
    _header = NULL;
    _count = 0; //記錄個(gè)數(shù)
    _waiters = 0;
    _owner = NULL;
    _WaitSet = NULL;//處于wait狀態(tài)的線程,會(huì)被加入到_WaitSet
    _WaitSetLock = 0;
    _EntryList = NULL;
    ...
    ...
}

這就是synchronized的全部嗎偏化?

當(dāng)然不是脐恩。
在以前的認(rèn)知中,我們認(rèn)為synchronized的性能會(huì)比Lock差很多侦讨,但是在jdk6之后驶冒,synchronized得到了一次性能優(yōu)化苟翻,這次性能優(yōu)化,就是鎖膨脹骗污。

鎖膨脹

鎖膨脹用一句話簡單概括就是崇猫,一個(gè)鎖經(jīng)過三次膨脹變的笨重的但穩(wěn)重過程。

換句話講身堡,每一個(gè)對(duì)象邓尤,都有四種鎖的狀態(tài)拍鲤。
由淺至深贴谎,由弱變強(qiáng)分為:

無鎖 > 偏向鎖 > 輕量級(jí)鎖 > 重量級(jí)鎖

這四個(gè)狀態(tài)是怎么區(qū)分的呢?

對(duì)象頭中的Mark word區(qū)域季稳,存儲(chǔ)著對(duì)象的哈希值擅这,GC年齡,鎖標(biāo)記位景鼠,是否偏向仲翎,偏向線程等數(shù)據(jù)。

鎖狀態(tài) 是否偏向 鎖標(biāo)志位
無鎖 0 00
偏向鎖 1 01
輕量級(jí)鎖 00
重量級(jí)鎖 10
無鎖狀態(tài):當(dāng)對(duì)象從來沒有線程請求獲取鎖铛漓。
偏向鎖溯香,何為偏向,是指該實(shí)例將會(huì)偏向第一個(gè)來獲取它的鎖的線程浓恶,如果沒有其它線程來請求獲取鎖玫坛,則持有該鎖的線程永遠(yuǎn)不需要同步。
  1. 當(dāng)鎖第一次被線程獲取時(shí)包晰,通過CAS將線程ID記錄到對(duì)象頭的Mark word中湿镀,并且修改偏向標(biāo)志,之后該線程在進(jìn)入和退出同步塊時(shí)伐憾,不需要進(jìn)行獲取鎖和釋放鎖的操作勉痴,僅測試Mark word中的線程ID
  2. 當(dāng)另外線程嘗試獲取該鎖時(shí),偏向模式結(jié)束
  3. 新線程發(fā)現(xiàn)該對(duì)象的偏向狀態(tài)時(shí)树肃,表明已經(jīng)存在競爭
  4. 檢查該鎖偏向的線程是否存活
  5. 如果原線程掛掉的話則恢復(fù)到無鎖狀態(tài)并重新偏向到新的線程
  6. 如果原線程依然存活蒸矛,則檢查原線程的操作棧是否需要使用該鎖
  7. 如果原線程不需要使用該鎖,則對(duì)象狀態(tài)恢復(fù)到無鎖狀態(tài)并重新偏向到新的線程
  8. 如果原線程仍然需要使用該鎖胸嘴,則偏向鎖升級(jí)為輕量級(jí)鎖
輕量級(jí)鎖 雏掠,輕量級(jí)鎖是通過CAS來避免使用互斥量的開銷
  1. 當(dāng)獲取鎖的線程,檢查鎖狀態(tài)是否為無鎖(即:是否偏向->是筛谚,鎖標(biāo)志位->01偏向鎖)磁玉。
  2. 當(dāng)前線程將在當(dāng)前的棧幀中申請一塊空間,Lock Record(包含兩部分驾讲,一部分存放對(duì)象頭中的Mark Word的拷貝蚊伞,稱為Displaced Mark Word席赂,另一部分為指向owner)。
  3. 將對(duì)象頭中的Mark Word拷貝至Lock Record中时迫,并通過CAS操作將對(duì)象頭中Mark Word更新為指向Lock Record的指針颅停;將Lock Record中的owner通過CAS更新為指向?qū)ο箢^中Mark Word的指針
  4. 如果更新成功,則將對(duì)象頭中的鎖標(biāo)志位更新為00掠拳,即輕量級(jí)鎖
  5. 如果更新失敗癞揉,則檢查對(duì)象頭中的Mard Word是否指向當(dāng)前棧幀
  6. 如果是指向當(dāng)前棧幀,則表示已經(jīng)持有該鎖
  7. 如果不是溺欧,則代表產(chǎn)生競爭喊熟,膨脹為重量級(jí)鎖,更新鎖標(biāo)志位為10姐刁,Mark Word中存儲(chǔ)的就是指向重量級(jí)鎖的指針芥牌,后面等待鎖的線程也會(huì)進(jìn)入阻塞狀態(tài)
重量級(jí)鎖,即前文提到的Monitor聂使,其本質(zhì)是依賴于系統(tǒng)底層的Mutex Lock壁拉,也是性能開銷最大的狀態(tài)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柏靶,一起剝皮案震驚了整個(gè)濱河市弃理,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屎蜓,老刑警劉巖痘昌,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異梆靖,居然都是意外死亡控汉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門返吻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姑子,“玉大人,你說我怎么就攤上這事测僵〗钟樱” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵捍靠,是天一觀的道長沐旨。 經(jīng)常有香客問我,道長榨婆,這世上最難降的妖魔是什么磁携? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮良风,結(jié)果婚禮上谊迄,老公的妹妹穿的比我還像新娘闷供。我一直安慰自己,他們只是感情好统诺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布歪脏。 她就那樣靜靜地躺著,像睡著了一般粮呢。 火紅的嫁衣襯著肌膚如雪婿失。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天啄寡,我揣著相機(jī)與錄音豪硅,去河邊找鬼。 笑死这难,一個(gè)胖子當(dāng)著我的面吹牛舟误,可吹牛的內(nèi)容都是我干的葡秒。 我是一名探鬼主播姻乓,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼眯牧!你這毒婦竟也來了蹋岩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤学少,失蹤者是張志新(化名)和其女友劉穎剪个,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體版确,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扣囊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绒疗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侵歇。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吓蘑,靈堂內(nèi)的尸體忽然破棺而出惕虑,到底是詐尸還是另有隱情,我是刑警寧澤磨镶,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布溃蔫,位于F島的核電站,受9級(jí)特大地震影響琳猫,放射性物質(zhì)發(fā)生泄漏伟叛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一脐嫂、第九天 我趴在偏房一處隱蔽的房頂上張望统刮。 院中可真熱鬧侄榴,春花似錦、人聲如沸网沾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辉哥。三九已至桦山,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間醋旦,已是汗流浹背恒水。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饲齐,地道東北人钉凌。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像捂人,于是被迫代替她去往敵國和親御雕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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