JAVA并發(fā)Monitor工作原理圖解
一、前言
Monitor 是 Java 中實(shí)現(xiàn) 互斥鎖(Mutual Exclusion) 的核心工具。只有一個線程可以持有某個對象的 Monitor,其他線程必須阻塞等待,直到該線程釋放鎖,JVM 中每個對象在重量級鎖的情況才關(guān)聯(lián)著一個 Monitor,當(dāng)線程進(jìn)入 鎖等級為重量級的synchronized 代碼時,必須先獲得該對象的 Monitor。
二、Monitor 的數(shù)據(jù)結(jié)構(gòu)

三、Monitor 的工作流程
(1)某線程嘗試進(jìn)入同步代碼塊(monitorenter)
- 如果 Monitor 沒有被其他線程持有,線程獲得鎖(成為 Owner)。
- 如果已經(jīng)持有:
- 若是當(dāng)前線程自身(重入),增加計(jì)數(shù)器。
- 否則,進(jìn)入 Entry Queue 阻塞等待。
(2)退出同步代碼塊(monitorexit)
- 釋放鎖:減少計(jì)數(shù)器;
- 若計(jì)數(shù)為 0,則清空 Owner,并喚醒 Entry Queue 中的線程開始爭奪鎖。
(3)調(diào)用 wait/notify 時的行為
wait():- 當(dāng)前線程釋放鎖,加入 Wait Set,進(jìn)入等待狀態(tài);
notify():- 將 Wait Set 中隨機(jī)選擇一個線程移入 Entry Queue,等待重新競爭鎖。
工作流程圖解
線程零搶占到對象obj的鎖,此時EntryQueue中存放一二三線程等待搶鎖

此時對Thread-0調(diào)用wait()方法,Thread-0釋放鎖并且進(jìn)入WaitSet,EntryQueue隊(duì)列中的線程隨機(jī)獲取鎖,假設(shè)Thread-2獲取到鎖

此時EntryQueue中的線程處于阻塞狀態(tài)(BLOCKED),等待Thread-2釋放鎖再進(jìn)行搶鎖
而此時Thread-0線程進(jìn)入等待狀態(tài)(WAITING或TIMED_WAITING),不參與鎖的競爭,只有恢復(fù)阻塞狀態(tài)時才去參與鎖的競爭
想要從等待狀態(tài)恢復(fù)為阻塞狀態(tài)的三種方法
- 其他線程調(diào)用
notify()或notifyAll()喚醒它 - 等待超時(如果使用了
wait(long timeout)方法) - 被中斷(調(diào)用
interrupt()方法)
四、Monitor 和鎖的演進(jìn)機(jī)制
JVM 為了性能優(yōu)化,提供了 鎖優(yōu)化策略:
| 鎖類型 | 描述 |
|---|---|
| 無鎖 | 默認(rèn)狀態(tài),適用于單線程環(huán)境,Mark Word 存儲對象的哈希碼、分代年齡等信息。 |
| 偏向鎖 | 偏向于第一個訪問線程,后續(xù)無競爭,Mark Word 會被替換為鎖標(biāo)志位(01)和持有鎖的線程ID |
| 輕量級鎖 | 多線程但無阻塞,通過 CAS 競爭
|
| 重量級鎖 | Monitor 對象控制,線程進(jìn)入阻塞隊(duì)列,性能開銷大,Mark Word 中存儲指向 Monitor 對象(管程/互斥量)的指針 |

五、Monitor 的作用總結(jié)表
| 功能 | 描述 |
|---|---|
| 互斥訪問 | 確保同一時間內(nèi)只有一個線程訪問共享資源 |
| 可重入性 | 同一線程可重復(fù)進(jìn)入臨界區(qū) |
| 線程協(xié)作(條件變量) | 支持 wait/notify 機(jī)制 |
| 阻塞調(diào)度 | 管理 Entry Queue 和 Wait Set 的線程阻塞與喚醒 |
| 性能優(yōu)化依據(jù) | 鎖升級的核心控制結(jié)構(gòu) |
到此這篇關(guān)于JAVA并發(fā)Monitor工作原理圖解的文章就介紹到這了,更多相關(guān)java并發(fā)Monitor工作原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文學(xué)會如何在SpringBoot中使用線程池執(zhí)行定時任務(wù)
在開發(fā)現(xiàn)代應(yīng)用程序時,定時任務(wù)是一項(xiàng)常見的需求,SpringBoot提供了一個強(qiáng)大的定時任務(wù)框架,可以輕松地執(zhí)行各種定時任務(wù),結(jié)合線程池的使用,可以更好地管理任務(wù)的執(zhí)行,提高系統(tǒng)的性能和穩(wěn)定性,本文將介紹如何在Spring Boot中使用線程池執(zhí)行定時任務(wù)2023-06-06
Java數(shù)據(jù)結(jié)構(gòu)-HashMap詳解
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)-HashMap,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
關(guān)于在使用Lombok時maven?install找不到符號問題的解決辦法
Maven環(huán)境下開發(fā)項(xiàng)目時,尤其是涉及Lombok或其他依賴時,IDE會在構(gòu)建和編譯過程中進(jìn)行注解處理,這篇文章主要介紹了關(guān)于在使用Lombok時maven?install找不到符號問題的解決辦法,需要的朋友可以參考下2025-10-10
Spring?Boot?集成?Swagger2構(gòu)建?API文檔
這篇文章主要介紹了Spring?Boot?集成?Swagger2構(gòu)建?API文檔,通過使用?Swagger,我們只需要按照它所給定的一系列規(guī)范去定義接口以及接口的相關(guān)信息,然后它就能幫我們自動生成各種格式的接口文檔,方便前后端開發(fā)者進(jìn)行前后端聯(lián)調(diào),下文需要的朋友可以參考一下2022-03-03

