《Java并发编程的艺术》之synchronized的底层实现原理
在學(xué)習(xí)鎖優(yōu)化時(shí),對(duì)象頭(Mark Word) 是必不可缺的一環(huán),因?yàn)閟ynchronized 用的鎖是存在對(duì)象頭里的。32位的虛擬機(jī)上對(duì)象頭占64位(8字節(jié)),64位的虛擬機(jī)上對(duì)象頭占128位(16字節(jié))[^objectHead];而不同的類(lèi)型,對(duì)象頭的布局不太一樣:
- 數(shù)組類(lèi)型:Mark Word、Class Metadata Address、Array Length
- 普通類(lèi)型:Mark Word、Class Metadata Address
Mark Word 表示對(duì)象的HashCode 或 鎖信息
Class Metadata Address 表示對(duì)象的數(shù)據(jù)類(lèi)型在方法區(qū)對(duì)應(yīng)的地址
Array Length 表示數(shù)組的長(zhǎng)度(只在對(duì)象是數(shù)組的情況下才會(huì)存在)
對(duì)象頭的默認(rèn)表示應(yīng)該如下所示
| 無(wú)狀態(tài)鎖 | 對(duì)象的hashcode | 對(duì)象分代年齡 | 0 | 01 |
具體的對(duì)象內(nèi)存布局看這篇文章
而根據(jù)JVM的設(shè)置1,具體分配時(shí)又會(huì)有不同的情況,如下所示
當(dāng)關(guān)閉了偏向鎖的設(shè)置,那么就會(huì)走左邊的流程;反之則走右邊的流程。
偏向鎖
由于大多數(shù)情況下,鎖大多都不處于多線程競(jìng)爭(zhēng)狀態(tài),而且總是由同一個(gè)線程獲取,所以JVM在1.6之后加入了偏向鎖 和 輕量鎖 ,如今總共由4種鎖狀態(tài):無(wú)狀態(tài)鎖、偏向鎖、輕量鎖、重量鎖。隨著線程競(jìng)爭(zhēng)的提升,鎖會(huì)逐漸升級(jí)(無(wú)法降級(jí))。
偏向鎖在沒(méi)有競(jìng)爭(zhēng)的情況下可以提高同步的性能,這方面主要體現(xiàn)在偏向鎖只需要進(jìn)行一次CAS而輕量鎖需要兩次。它是一個(gè)需要權(quán)衡利弊的選擇,它不是在任何情況下都對(duì)程序有利的。如果競(jìng)爭(zhēng)很多,那么撤銷(xiāo)偏向鎖的過(guò)程就會(huì)成為性能瓶頸。
當(dāng)偏向鎖可用時(shí),初始化的對(duì)象頭分配如下所示
| 偏向鎖 | 線程ID | epoch | 對(duì)象分代年齡 | 1 | 01 |
加鎖過(guò)程
鎖撤銷(xiāo)
由于偏向鎖使用了一種直到競(jìng)爭(zhēng)發(fā)生時(shí)才會(huì)釋放的機(jī)制,所以當(dāng)其他線程競(jìng)爭(zhēng)偏向鎖時(shí),持有偏向鎖的線程才會(huì)去釋放鎖。
輕量鎖
加鎖過(guò)程
注意:輕量鎖會(huì)一直保持,喚醒總是發(fā)生在輕量鎖解鎖的時(shí)候,因?yàn)榧渔i的時(shí)候已經(jīng)成功CAS操作;而CAS失敗的線程,會(huì)立即鎖膨脹,并阻塞等待喚醒。
鎖釋放過(guò)程
總結(jié)
本章是對(duì)synchronized 在JVM里的各種等級(jí)及升級(jí)的流程進(jìn)行了講解,其中主要是通過(guò)控制對(duì)象頭的一些狀態(tài)來(lái)控制鎖的等級(jí)。偏向鎖通過(guò)標(biāo)記Thread ID 來(lái)表示,當(dāng)前對(duì)象已經(jīng)被對(duì)應(yīng)線程占用;輕量鎖則替換Mark Word 為 Lock Record 地址 來(lái)表示當(dāng)前對(duì)象被對(duì)應(yīng)線程占用。無(wú)論是哪種鎖,在不同的場(chǎng)景下有不同的需求,可以參考以下表格做出選擇
偏向鎖:
- 優(yōu)點(diǎn):加鎖和解鎖不需要額外消耗,和執(zhí)行非同步方法相比,僅存在納秒級(jí)的差距
- 缺點(diǎn):如果線程間存在競(jìng)爭(zhēng),會(huì)帶來(lái)額外開(kāi)銷(xiāo)(偏向鎖的撤銷(xiāo))
- 適用場(chǎng)景: 適用于只有一個(gè)線程訪問(wèn)同步塊的場(chǎng)景
輕量鎖:
- 優(yōu)點(diǎn): 競(jìng)爭(zhēng)的線程不會(huì)造成阻塞,提高了程序的響應(yīng)速度
- 缺點(diǎn): 如果始終得不到鎖,使用自旋會(huì)消耗CPU
- 適用場(chǎng)景: 追求相應(yīng)實(shí)踐,同步塊執(zhí)行速度非常快
重量鎖:
- 優(yōu)點(diǎn): 線程競(jìng)爭(zhēng)不使用自選,不會(huì)消耗CPU
- 缺點(diǎn): 線程阻塞,響應(yīng)時(shí)間緩慢
- 適用場(chǎng)景: 追求吞吐量,同步塊執(zhí)行速度較慢
這個(gè)是網(wǎng)上找到的關(guān)于鎖撤銷(xiāo)、膨脹等操作的總流程
關(guān)于偏向鎖的相關(guān)JVM設(shè)置:-XXBiasedLockingStartupDelay=0表示啟動(dòng)程序幾秒鐘后激活偏向鎖-XXUseBiasedLocking=false表示關(guān)閉偏向鎖(確定會(huì)發(fā)生競(jìng)爭(zhēng)時(shí)可以這么設(shè)置)?
轉(zhuǎn)載于:https://www.cnblogs.com/codeleven/p/10963092.html
總結(jié)
以上是生活随笔為你收集整理的《Java并发编程的艺术》之synchronized的底层实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【光学】基于matlab色散曲线拟合【含
- 下一篇: chrome java虚拟机_JATT: