Java synchronized重量級(jí)鎖實(shí)現(xiàn)過(guò)程淺析
一、什么是重量級(jí)鎖
當(dāng)有大量的線程都在競(jìng)爭(zhēng)同一把鎖的時(shí)候,這個(gè)時(shí)候加的鎖,就是重量級(jí)鎖。


這個(gè)重量級(jí)鎖其實(shí)指的就是JVM內(nèi)部的ObjectMonitor監(jiān)視器對(duì)象:
ObjectMonitor() {
_header = NULL; //鎖對(duì)象的原始對(duì)象頭
_count = 0; //搶占當(dāng)前鎖的線程數(shù)量
_waiters = 0, //調(diào)用wait方法后等待的線程數(shù)量
_recursions = 0; //記錄鎖重入次數(shù)
_object = NULL;
_owner = NULL; //指向持有ObjectMonitor的線程
_WaitSet = NULL; //處于wait狀態(tài)的線程隊(duì)列,等待被喚醒
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ; //等待鎖的線程隊(duì)列
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
_previous_owner_tid = 0;
}二、重量級(jí)鎖的演示
public class HightweightLockDemo02 {
public static void main(String[] args) {
Object objLock = new Object();
new Thread(() -> {
synchronized (objLock) {
System.out.println(ClassLayout.parseInstance(objLock).toPrintable());
}
}, "t1").start();
new Thread(() -> {
synchronized (objLock) {
System.out.println(ClassLayout.parseInstance(objLock).toPrintable());
}
}, "t2").start();
}
}運(yùn)行程序:
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 1a 33 c9 e1 (00011010 00110011 11001001 11100001) (-506907878)
4 4 (object header) 43 01 00 00 (01000011 00000001 00000000 00000000) (323)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 1a 33 c9 e1 (00011010 00110011 11001001 11100001) (-506907878)
4 4 (object header) 43 01 00 00 (01000011 00000001 00000000 00000000) (323)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
可見(jiàn),當(dāng)多個(gè)線程共同搶占同一把鎖的時(shí)候,鎖對(duì)象MarkWord的最后三位是“010”,代表的就是一個(gè)重量級(jí)鎖。
三、重量級(jí)鎖的原理
以上述代碼為例,synchronized獲取的鎖是重量級(jí)鎖,synchronized修飾代碼塊,使用javap -p -v .\HightweightLockDemo02.class指令查看其字節(jié)碼:

在編譯的時(shí)候,JVM會(huì)在同步塊開(kāi)始位置插入monitorenter指令,在同步塊結(jié)束位置插入monitorexit指令。當(dāng)線程執(zhí)行到monitorenter指令時(shí),會(huì)嘗試獲取對(duì)象所對(duì)應(yīng)的Monitor所有權(quán),如果獲取成功,則表示獲取到了鎖,會(huì)在Monitor的_owner中存在當(dāng)前線程的ID,這樣它將處于鎖定狀態(tài),除非退出同步塊,否則其他線程無(wú)法獲取得到這個(gè)Monitor。

四、鎖的優(yōu)缺點(diǎn)對(duì)比
下表是對(duì)各種狀態(tài)的鎖的對(duì)比:
| 鎖的類型 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
| 偏向鎖 | 加鎖和解鎖不需要額外的消耗,和執(zhí)行非同步方法相比僅存在納秒級(jí)的差距 | 如果線程間存在鎖競(jìng)爭(zhēng),會(huì)帶來(lái)額外的鎖撤銷的消耗 | 適用于只有一個(gè)線程訪問(wèn)同步塊場(chǎng)景 |
| 輕量級(jí)鎖 | 競(jìng)爭(zhēng)的線程不會(huì)阻塞,提高了程序的響應(yīng)速度 | 如果始終得不到鎖競(jìng)爭(zhēng)的線程,使用自旋會(huì)消耗CPU,導(dǎo)致CPU空轉(zhuǎn) | 追求響應(yīng)時(shí)間 同步塊執(zhí)行速度非???/td> |
| 重量級(jí)鎖 | 線程競(jìng)爭(zhēng)不使用自旋,不會(huì)消耗CPU | 線程阻塞,響應(yīng)時(shí)間緩慢 | 追求吞吐量 同步塊執(zhí)行時(shí)間較長(zhǎng) |
到此這篇關(guān)于Java synchronized重量級(jí)鎖實(shí)現(xiàn)過(guò)程淺析的文章就介紹到這了,更多相關(guān)Java synchronized 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java同步鎖Synchronized底層源碼和原理剖析(推薦)
- java同步鎖的正確使用方法(必看篇)
- 95%的Java程序員人都用不好Synchronized詳解
- Java?synchronized同步關(guān)鍵字工作原理
- Java synchronized偏向鎖的概念與使用
- Java?synchronized輕量級(jí)鎖實(shí)現(xiàn)過(guò)程淺析
- Java @Transactional與synchronized使用的問(wèn)題
- Java?synchronized與死鎖深入探究
- Java synchronized與CAS使用方式詳解
- 淺析Java關(guān)鍵詞synchronized的使用
- synchronized及JUC顯式locks?使用原理解析
- java鎖synchronized面試常問(wèn)總結(jié)
- Java?HashTable與Collections.synchronizedMap源碼深入解析
- Java?Synchronized鎖的使用詳解
- AQS加鎖機(jī)制Synchronized相似點(diǎn)詳解
- Java必會(huì)的Synchronized底層原理剖析
- 一個(gè)例子帶你看懂Java中synchronized關(guān)鍵字到底怎么用
- 詳解Java?Synchronized的實(shí)現(xiàn)原理
- Synchronized?和?ReentrantLock?的實(shí)現(xiàn)原理及區(qū)別
- Java同步鎖synchronized用法的最全總結(jié)
相關(guān)文章
徹底理解Spring注解@Autowired實(shí)現(xiàn)原理
這篇文章主要為大家詳細(xì)的介紹了Spring注解@Autowired實(shí)現(xiàn)的原理,縝密的邏輯分析,實(shí)踐應(yīng)用示例操作說(shuō)明,讓大家徹底的理解Spring注解@Autowired背后實(shí)現(xiàn)原理2022-03-03
Java異常處理之try...catch...finally詳解
今天小編就為大家分享一篇關(guān)于Java異常處理之try...catch...finally詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01
Java代理的幾種實(shí)現(xiàn)方式總結(jié)
本文將通過(guò)例子說(shuō)明java代理的幾種實(shí)現(xiàn)方式,并比較它們之間的差異,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-12-12
JAVA實(shí)戰(zhàn)練習(xí)之圖書管理系統(tǒng)實(shí)現(xiàn)流程
隨著網(wǎng)絡(luò)技術(shù)的高速發(fā)展,計(jì)算機(jī)應(yīng)用的普及,利用計(jì)算機(jī)對(duì)圖書館的日常工作進(jìn)行管理勢(shì)在必行,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)圖書管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-10-10
SpringBoot實(shí)現(xiàn)熱部署的三種方式
本文主要介紹了SpringBoot實(shí)現(xiàn)熱部署的三種方式,主要包括配置pom.xml文件,使用插件的執(zhí)行命令mvn spring-boot:run啟動(dòng)項(xiàng),使用springloader本地啟動(dòng)修改jvm參數(shù),使用devtools工具包,感興趣的可以了解一下2023-12-12
Java中的stream流的概念解析及實(shí)際運(yùn)用總結(jié)
流是指?jìng)鬏敃r(shí)的數(shù)據(jù),Java為流準(zhǔn)備了很多內(nèi)置類,尤其是IO輸入輸出流非常常用,這里我們來(lái)看一下Java中的stream流的概念解析及實(shí)際運(yùn)用總結(jié)2016-06-06
SpringBoot中的異常處理與參數(shù)校驗(yàn)的方法實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot中的異常處理與參數(shù)校驗(yàn)的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
springboot?publish?event?事件機(jī)制demo分享
這篇文章主要介紹了springboot?publish?event?事件機(jī)制demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10

