【java并發(fā)編程實(shí)戰(zhàn)4】偏向鎖-輕量鎖-重量鎖的那點(diǎn)秘密(synchronize實(shí)現(xiàn)原理)

目錄

【SpringBoot2.0文章匯總目錄沐批,java多線程教程文章匯總 長(zhǎng)期更新系列

請(qǐng)多多支持

在多線程并發(fā)編程中,synchronized一直都是元老級(jí)別的角色,人們都通常稱呼它為重量鎖,但是在jdk1.6版本之后,jdk就對(duì)synchronized做了大量的優(yōu)化凳怨,這時(shí)候我們就不能稱呼它為重量鎖了,有的時(shí)候它也是很的是鬼,那么接下來(lái)我們就調(diào)調(diào)肤舞,synchronized是怎么被優(yōu)化的,它跟偏向鎖屑咳、輕量鎖萨赁、重量鎖又有什么淵源。

synchronized

回顧一下synchronized是怎么使用的呢兆龙。

1杖爽、同步普通方法

public synchronized void  sync1() {
    // do somethings
}

在該方法中,synchronized鎖的是當(dāng)前實(shí)例的對(duì)象

2紫皇、同步靜態(tài)方法

public static synchronized void sync2() {
    // do somethings
}

由于該方法是一個(gè)靜態(tài)方法慰安,那么它鎖的當(dāng)前類的class對(duì)象。

3聪铺、同步方法塊

public void sync3() {
    synchronized(this) {
        // do somethings
    }
}

public void sync4() {
    synchronized(MyTest.css) {
        // do somethings
    }
}

那么同步方法塊是需要根據(jù)方法中具體同步的對(duì)象來(lái)實(shí)現(xiàn)的化焕。

在上面代碼中其實(shí)sync3()跟同步普通方法一樣,鎖的是當(dāng)前實(shí)例對(duì)象铃剔;那么sync4方法就與同步靜態(tài)方法一樣撒桨,鎖的是當(dāng)前類的class對(duì)象查刻。

從上面代碼可以看出來(lái)的,我們通過(guò)使用synchronized關(guān)鍵字可以很簡(jiǎn)單的解決并發(fā)問(wèn)題凤类,但是其實(shí)是jvm底層通過(guò)使用一種叫內(nèi)置鎖的手段穗泵,簡(jiǎn)化了開(kāi)發(fā)人員實(shí)現(xiàn)并發(fā)的復(fù)雜度,在jdk1.6以前 synchronized是基于重量鎖實(shí)現(xiàn)的谜疤,即每次遇到同步代碼都要獲取鎖佃延,然后釋放鎖,在jdk1.6之后對(duì)其優(yōu)化夷磕,根據(jù)不同場(chǎng)景使用不同的策略履肃,這也就是 偏向鎖、輕量鎖坐桩、重量鎖的來(lái)由尺棋。在介紹他們之前我先介紹一下另一個(gè)鎖-自旋鎖。聽(tīng)到這么多鎖撕攒,是不是頭暈陡鹃,當(dāng)初我學(xué)習(xí)的時(shí)候也是這樣的。但是當(dāng)你慢慢學(xué)習(xí)深入抖坪,你就會(huì)很容易的理解每個(gè)鎖的作用。

自旋鎖

自旋鎖顧名思義闷叉,就是自己旋轉(zhuǎn)轉(zhuǎn)圈等待擦俐,那么它有什么作用呢?

  • 當(dāng)前線程嘗試去競(jìng)爭(zhēng)鎖
  • 競(jìng)爭(zhēng)失敗握侧,準(zhǔn)備阻塞自己
  • 但是并沒(méi)有阻塞自己蚯瞧,而是采用自旋鎖,進(jìn)入自旋狀態(tài)
  • 進(jìn)入自旋狀態(tài)品擎,并且重新不斷競(jìng)爭(zhēng)鎖
  • 如果在自旋期間成功獲取鎖埋合,那么結(jié)束自旋狀態(tài),否則進(jìn)入阻塞狀態(tài)

如果在自旋期間成功獲取鎖萄传,那么就減少一次線程的切換甚颂。

根據(jù)上面解釋我們可以很容易的明白自旋鎖的意義,因?yàn)閏pu從內(nèi)核態(tài)切換至用戶態(tài)秀菱,線程的阻塞與恢復(fù)會(huì)浪費(fèi)資源的振诬,但是通過(guò)自旋而不是去阻塞當(dāng)前線程,那么就會(huì)節(jié)省這個(gè)一個(gè)cpu狀態(tài)切換衍菱。

所以自旋鎖適合在** 持有鎖的時(shí)間長(zhǎng)赶么,且競(jìng)爭(zhēng)不激烈**的場(chǎng)景下使用。

使用-XX:-UseSpinning參數(shù)關(guān)閉自旋鎖優(yōu)化脊串;-XX:PreBlockSpin參數(shù)修改默認(rèn)的自旋次數(shù)

偏向鎖

在實(shí)際場(chǎng)景中辫呻,如果一個(gè)同步方法清钥,沒(méi)有多線程競(jìng)爭(zhēng),并且總是由同一個(gè)線程多次獲取鎖放闺,如果每次還有阻塞線程祟昭,喚醒cpu從用戶態(tài)轉(zhuǎn)核心態(tài),那么對(duì)于cpu是一種資源的浪費(fèi)雄人,為了解決這類問(wèn)題从橘,舊引入了偏向鎖的概念。

“偏向”的意思是础钠,偏向鎖假定將來(lái)只有第一個(gè)申請(qǐng)鎖的線程會(huì)使用鎖(不會(huì)有任何線程再來(lái)申請(qǐng)鎖)恰力,因此,只需要在Mark Word中CAS記錄owner(本質(zhì)上也是更新旗吁,但初始值為空)踩萎,如果記錄成功,則偏向鎖獲取成功很钓,記錄鎖狀態(tài)為偏向鎖香府,以后當(dāng)前線程等于owner就可以零成本的直接獲得鎖;否則码倦,說(shuō)明有其他線程競(jìng)爭(zhēng)企孩,膨脹為輕量級(jí)鎖

具體的步驟如下

  • 訪問(wèn)同步代碼塊

  • 檢查對(duì)象頭是否owner是否存儲(chǔ)當(dāng)前現(xiàn)成的id

  • 如果沒(méi)有袁稽,進(jìn)行CAS嘗試替換mark word中的owner 如果有執(zhí)行同步代碼(代表獲取鎖成功)

  • 修改成功 (代表無(wú)競(jìng)爭(zhēng))owner修改為當(dāng)前線程id,執(zhí)行同步代碼 修改失敗(代表有競(jìng)爭(zhēng)) 進(jìn)入撤銷偏向鎖勿璃,暫停線程并將owner置空,進(jìn)入輕量鎖推汽。

899685-20161025102843468-151954717.png

偏向鎖無(wú)法使用自旋鎖優(yōu)化补疑,因?yàn)橐坏┯衅渌€程申請(qǐng)鎖,就破壞了偏向鎖的假定歹撒。

如果你確定應(yīng)用程序中所有的鎖通常是在競(jìng)爭(zhēng)狀態(tài)莲组,你可以通過(guò)JVM參數(shù)關(guān)閉偏向鎖

UseBiasedLocking = false,那么程序會(huì)默認(rèn)進(jìn)入輕量鎖狀態(tài)暖夭。

輕量鎖

如果說(shuō)偏向鎖是為了解決同步代碼在單線程下訪問(wèn)性能問(wèn)題锹杈,那么輕量鎖是為了解決減少無(wú)實(shí)際競(jìng)爭(zhēng)情況下,使用重量級(jí)鎖產(chǎn)生的性能消耗

輕量鎖鳞尔,顧名思義嬉橙,輕量是相對(duì)于重量的問(wèn)題,使用輕量鎖時(shí)寥假,不需要申請(qǐng)互斥量(mutex)

,而是將mark word中的信息復(fù)制到當(dāng)前線程的棧中市框,然后通過(guò)cas嘗試修改mark word并替換成輕量鎖,如果替換成功則執(zhí)行同步代碼糕韧。如果此時(shí)有線程2來(lái)競(jìng)爭(zhēng)枫振,并且他也嘗試cas修改mark word但是失敗了喻圃,那么線程2會(huì)進(jìn)入自旋狀態(tài),如果在自旋狀態(tài)也沒(méi)有修改成功粪滤,那么輕量鎖將膨脹成狀態(tài)斧拍,mark word會(huì)被修改成重量鎖標(biāo)記(10) ,線程進(jìn)入阻塞狀態(tài)。

當(dāng)然杖小,由于輕量級(jí)鎖天然瞄準(zhǔn)不存在鎖競(jìng)爭(zhēng)的場(chǎng)景肆汹,如果存在鎖競(jìng)爭(zhēng)但不激烈,仍然可以用自旋鎖優(yōu)化予权,自旋失敗后再膨脹為重量級(jí)鎖昂勉。

重量鎖

在jvm規(guī)范中,synchronized是基于監(jiān)視器鎖(monitor)來(lái)實(shí)現(xiàn)的扫腺,它會(huì)在同步代碼之前添加一個(gè)monitorenter指令岗照,獲取到該對(duì)象的monitor,同時(shí)它會(huì)在同步代碼結(jié)束處和異常處添加一個(gè)monitorexit指令去釋放該對(duì)象的monitor,需要注意的是每一個(gè)對(duì)象都有一個(gè)monitor與之配對(duì)笆环,當(dāng)一個(gè)monitor被獲取之后 也就是被monitorenter攒至,它會(huì)處于一個(gè)鎖定狀態(tài),其他嘗試獲取該對(duì)象的monitor的線程會(huì)獲取失敗躁劣,只有當(dāng)獲取該對(duì)象的monitor的線程執(zhí)行了monitorexit指令后迫吐,其他線程才有可能獲取該對(duì)象的monitor成功。

所以從上面描述可以得出账忘,監(jiān)視器鎖就是monitor它是互斥的(mutex)渠抹。由于它是互斥的,那么它的操作成本就非常的高闪萄,包括系統(tǒng)調(diào)用引起的內(nèi)核態(tài)與用戶態(tài)切換、線程阻塞造成的線程切換等奇颠。因此败去,后來(lái)稱這種鎖為“重量級(jí)鎖”。

小結(jié)

偏向鎖烈拒、輕量級(jí)鎖圆裕、重量級(jí)鎖適用于不同的并發(fā)場(chǎng)景:

  • 偏向鎖:無(wú)實(shí)際競(jìng)爭(zhēng),且將來(lái)只有第一個(gè)申請(qǐng)鎖的線程會(huì)使用鎖荆几。
  • 輕量級(jí)鎖:無(wú)實(shí)際競(jìng)爭(zhēng)吓妆,多個(gè)線程交替使用鎖;允許短時(shí)間的鎖競(jìng)爭(zhēng)吨铸。
  • 重量級(jí)鎖:有實(shí)際競(jìng)爭(zhēng)行拢,且鎖競(jìng)爭(zhēng)時(shí)間長(zhǎng)。

另外诞吱,如果鎖競(jìng)爭(zhēng)時(shí)間短舟奠,可以使用自旋鎖進(jìn)一步優(yōu)化輕量級(jí)鎖竭缝、重量級(jí)鎖的性能,減少線程切換沼瘫。

如果鎖競(jìng)爭(zhēng)程度逐漸提高(緩慢)抬纸,那么從偏向鎖逐步膨脹到重量鎖,能夠提高系統(tǒng)的整體性能耿戚。
同時(shí)需要注意鎖可以升級(jí)湿故,但是不能降級(jí)

另外通過(guò)這次學(xué)習(xí)膜蛔,大家應(yīng)該也知道自從jdk1.6以后 synchronized已經(jīng)被優(yōu)化了坛猪,性能不會(huì)比Lock

所以jdk.16版本及其以后版本的同學(xué)可以放心大膽的使用了。

最后附一張從偏向鎖膨脹至重量鎖的完全的流程圖

4491294-e3bcefb2bacea224.png

最后歡迎大家關(guān)注一下我的個(gè)人公眾號(hào)飞几。一起交流一起學(xué)習(xí)砚哆,有問(wèn)必答。


公眾號(hào)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末屑墨,一起剝皮案震驚了整個(gè)濱河市躁锁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卵史,老刑警劉巖战转,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異以躯,居然都是意外死亡槐秧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門忧设,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)刁标,“玉大人,你說(shuō)我怎么就攤上這事址晕“蛐福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵谨垃,是天一觀的道長(zhǎng)启搂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)刘陶,這世上最難降的妖魔是什么胳赌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮匙隔,結(jié)果婚禮上疑苫,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好缀匕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布纳决。 她就那樣靜靜地躺著,像睡著了一般乡小。 火紅的嫁衣襯著肌膚如雪阔加。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天满钟,我揣著相機(jī)與錄音胜榔,去河邊找鬼。 笑死湃番,一個(gè)胖子當(dāng)著我的面吹牛夭织,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吠撮,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼尊惰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了泥兰?” 一聲冷哼從身側(cè)響起弄屡,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鞋诗,沒(méi)想到半個(gè)月后膀捷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡削彬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年全庸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片融痛。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壶笼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雁刷,到底是詐尸還是另有隱情拌消,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布安券,位于F島的核電站,受9級(jí)特大地震影響氓英,放射性物質(zhì)發(fā)生泄漏侯勉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一铝阐、第九天 我趴在偏房一處隱蔽的房頂上張望址貌。 院中可真熱鬧,春花似錦、人聲如沸练对。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)螟凭。三九已至虚青,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間螺男,已是汗流浹背棒厘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留下隧,地道東北人奢人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淆院,于是被迫代替她去往敵國(guó)和親何乎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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