JAVA synchronized關鍵字涉及的Monitor對象中 EntryList和WaitSet工作機制

在Java的synchronized同步機制中,Monitor對象的EntryList和WaitSet是兩個關鍵隊列,它們分別管理不同狀態的線程。下面我將詳細解釋它們的工作原理,并提供代碼示例說明。

EntryList(鎖競爭隊列)

作用機制

EntryList保存了所有等待獲取鎖的線程。當鎖被某個線程持有時,其他嘗試獲取該鎖的線程會被放入EntryList中,處于BLOCKED狀態。

工作流程

  1. 線程嘗試獲取鎖時發現鎖已被持有
  2. 線程被放入EntryList等待
  3. 當持有鎖的線程釋放鎖時,JVM會從EntryList中選擇一個線程喚醒
  4. 被喚醒的線程嘗試獲取鎖

代碼示例

public class EntryListDemo {private static final Object lock = new Object();public static void main(String[] args) {// 線程1先獲取鎖new Thread(() -> {synchronized (lock) {System.out.println("線程1獲取鎖");try {Thread.sleep(3000); // 模擬長時間操作} catch (InterruptedException e) {e.printStackTrace();}System.out.println("線程1釋放鎖");}}).start();// 線程2稍后嘗試獲取鎖new Thread(() -> {try {Thread.sleep(100); // 確保線程1先獲取鎖} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) { // 這里會被放入EntryList等待System.out.println("線程2獲取鎖");}}).start();}
}

輸出結果

線程1獲取鎖
(等待約3秒)
線程1釋放鎖
線程2獲取鎖

WaitSet(等待隊列)

作用機制

WaitSet保存了調用了wait()方法的線程。這些線程已經獲得了鎖,但主動釋放鎖并等待被喚醒。

工作流程

  1. 線程獲得鎖后調用wait()方法
  2. 線程釋放鎖并進入WaitSet,處于WAITING狀態
  3. 其他線程調用notify()/notifyAll()時,線程從WaitSet轉移到EntryList
  4. 當再次獲得鎖時,從wait()調用處繼續執行

代碼示例

public class WaitSetDemo {private static final Object lock = new Object();private static volatile boolean condition = false;public static void main(String[] args) throws InterruptedException {// 等待線程Thread waitingThread = new Thread(() -> {synchronized (lock) {System.out.println("等待線程獲得鎖");while (!condition) {try {System.out.println("等待線程調用wait()");lock.wait(); // 釋放鎖并進入WaitSetSystem.out.println("等待線程被喚醒");} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("等待線程完成工作");}});// 通知線程Thread notifyingThread = new Thread(() -> {synchronized (lock) {System.out.println("通知線程獲得鎖");condition = true;lock.notify(); // 喚醒WaitSet中的一個線程System.out.println("通知線程已發送通知");}});waitingThread.start();Thread.sleep(500); // 確保等待線程先執行notifyingThread.start();}
}

輸出結果

等待線程獲得鎖
等待線程調用wait()
通知線程獲得鎖
通知線程已發送通知
等待線程被喚醒
等待線程完成工作

EntryList和WaitSet的區別

特性EntryListWaitSet
線程狀態BLOCKEDWAITING
進入方式競爭鎖失敗自動進入主動調用wait()進入
喚醒方式鎖釋放時自動喚醒必須通過notify()/notifyAll()
鎖的狀態從未獲得過鎖曾獲得鎖但主動釋放
轉移目標獲得鎖后進入運行狀態被喚醒后進入EntryList

完整生命周期示例

public class MonitorLifecycleDemo {private static final Object lock = new Object();public static void main(String[] args) {// 線程1:演示wait()和notify()new Thread(() -> {synchronized (lock) {System.out.println("線程1獲得鎖");try {System.out.println("線程1調用wait()進入WaitSet");lock.wait(); // 進入WaitSetSystem.out.println("線程1被喚醒,重新獲得鎖");} catch (InterruptedException e) {e.printStackTrace();}System.out.println("線程1釋放鎖");}}).start();// 線程2:競爭鎖進入EntryListnew Thread(() -> {try {Thread.sleep(100); // 確保線程1先獲得鎖} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) {System.out.println("線程2從EntryList中被選中獲得鎖");System.out.println("線程2調用notify()喚醒WaitSet中的線程");lock.notify(); // 喚醒線程1,線程1進入EntryListtry {Thread.sleep(1000); // 保持鎖一段時間} catch (InterruptedException e) {e.printStackTrace();}System.out.println("線程2釋放鎖");}}).start();// 線程3:展示EntryList中的競爭new Thread(() -> {try {Thread.sleep(200); // 確保線程2已獲得鎖} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock) {System.out.println("線程3獲得鎖");}}).start();}
}

輸出結果

線程1獲得鎖
線程1調用wait()進入WaitSet
線程2從EntryList中被選中獲得鎖
線程2調用notify()喚醒WaitSet中的線程
(等待約1秒)
線程2釋放鎖
線程1被喚醒,重新獲得鎖
線程1釋放鎖
線程3獲得鎖

這個示例展示了:

  1. 線程1獲得鎖后主動wait()進入WaitSet
  2. 線程2從EntryList中獲得鎖并notify()喚醒線程1
  3. 線程2釋放鎖后,線程1從WaitSet轉移到EntryList并重新獲得鎖
  4. 最后線程3獲得鎖

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88091.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88091.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88091.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

js-day10

JS學習之旅-day101. 作用域1.1 局部作用域1.2 全局作用域1.3 作用域鏈1.4 JS垃圾回收機制(GC)1.5 閉包1.6 變量提升2. 函數進階2.1 函數提升2.2 函數參數2.3 箭頭函數3. 解構賦值3.1 數組解構3.2 對象解構4. 數組遍歷4.1 forEach4.2 filter1. 作用域 作…

智能數字式毫秒計在實際生活場景中的應用

在電力領域,SYN5307型數字毫秒表可精準監測特高壓變電站斷路器合閘時間差,定位繼電保護裝置信號延遲;工業自動化中,優化汽車焊裝線時序、提升半導體晶圓切割良率;科研計量上,助力量子通信同步校準&#xff…

Java面試基礎:概念

1. Java的特點跨平臺性:Java的 “編寫一次,運行無處不在” 是其最大的特點之一。Java編譯器將源代碼編譯成字節碼(bytecode),該字節碼可以在任何安裝了Java虛擬機(JVM)的系統上運行。面向對象:Java是一門嚴格的面向對象編程語言&a…

PyQt5高級窗口控件詳解:停靠窗口、多文檔界面與滾動條

掌握PyQt5的高級窗口控件,讓你的GUI應用具備專業級的布局與交互體驗 在PyQt5應用開發中,高效管理窗口布局和實現復雜交互功能是提升用戶體驗的關鍵。本文將深入解析三個核心高級控件:停靠窗口(QDockWidget)、多文檔界面…

50天50個小項目 (Vue3 + Tailwindcss V4) ? | DrawingApp(畫板組件)

&#x1f4c5; 我們繼續 50 個小項目挑戰&#xff01;—— DrawingApp組件 倉庫地址&#xff1a;https://github.com/SunACong/50-vue-projects 項目預覽地址&#xff1a;https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API&#xff08;<script setup>…

Eureka、Nacos、LoadBalance、OpenFeign?之間的區別聯系和協作 (附代碼講解)

這篇文章聊聊微服務里的這幾個老伙計&#xff1a;Eureka、Nacos、LoadBalance、OpenFeign。咱們做微服務開發&#xff0c;總會跟這幾個組件打交道&#xff1a;Eureka、Nacos、Spring Cloud LoadBalancer、OpenFeign。它們各司其職又互相配合&#xff0c;今天就把它們的關系、用…

JavaSE-繼承

繼承&#xff08;inheritance&#xff09;繼承的意義我們首先來看下面兩個類&#xff1a;public class Dog {public String name;public int age;public void eat(){System.out.println(this.name"正在吃飯");}public void bark(){System.out.println(this.name"…

第二屆虛擬現實、圖像和信號處理國際學術會議(VRISP 2025)

重要信息 官網&#xff1a;www.icvisp.net 時間&#xff1a;2025年8月1-3日 地點&#xff1a;中國-長沙 簡介 近年來&#xff0c;虛擬現實技術取得了顯著進步&#xff0c;與5G、云計算和物聯網等新一代信息技術的融合加速&#xff0c;推動了其在硬件、軟件和內容應用等方面…

SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分離版:整體布局、架構調整(二)

目錄 一、前言 二、后端調整 1.實體類調整 2.菜單相關接口 3.用戶相關接口 4.新增工具類 5.新增菜單樹返回類 6.配置類、攔截器 三、前端調整 1.請求調整 2.頁面布局、樣式調整 1.user.vue 2.index.vue 3.請求攔截 四、開發過程中的問題 五、附&#xff1a…

vue3官方文檔學習心得

這幾天抽空把vue3的文檔整個看了一遍。簡介 | Vue.js 23年寫過一個vue2的項目&#xff0c;24年寫了一個vue3的項目&#xff0c;頁面功能比較簡單&#xff0c;用幾個簡單的API&#xff0c;watch、watchEffect、ref、reactive就能實現的業務功能。 寫了幾年的react的&#xff0…

Pycharm恢復默認設置,配置導致復制粘貼等不能使用

在file 種找到manage IDE settings在manage IDE settings中找到restore default settings

【王樹森推薦系統】召回12:曝光過濾 Bloom Filter

概述 曝光過濾通常是在召回階段做&#xff0c;具體的方法就是用 Bloom Filter 曝光過濾問題 如果用戶看過某個物品&#xff0c;則不再把該物品曝光給用戶。原因是同一個物品重復曝光給用戶會損害用戶體驗&#xff0c;但也不是所有推薦系統都有曝光過濾&#xff0c;像 youtube 這…

基于STM32單片機的心率血氧監測系統設計(STM32代碼編寫+手機APP設計+PCB設計+Proteus仿真)

系列文章目錄 文章目錄 系列文章目錄前言1 資料獲取與演示視頻1.1 資料介紹1.2 資料獲取1.3 演示視頻 2 系統框架3 硬件3.1 主控制器3.2 顯示屏3.3 WIFI模塊3.4心率血氧傳感器 4 設計PCB4.1 安裝下載立創EDA專業版4.2 畫原理圖4.4 使用嘉立創下單助手進行下單&#xff0c;打板。…

main(int argc,char **agrv)的含義

今天和大家討論一個常見的但是不容易深入了解的知識點。那就是 main 函數聲明中使用到的 argc 和 argv 的含義。通常我們寫主函數的時候一般都是直接使用int main() 或者 void main() 來聲明 main 函數。但是你知道嗎&#xff1f;在c89/c99的語言標準中&#xff0c;main函數的聲…

如何簡單實現發版不影響客戶使用?nginx負載

nginx負載發版不影響客戶使用 1.需要二臺服務器 2.二臺服務器均是正式環境配置 3.服務器Nginx配置修改 發版順序&#xff1a;先在服務器2發版&#xff0c;發布成功后&#xff0c;再改服務器Nginx配置&#xff0c;重新加載nginx&#xff1b;然后在服務器再發版&#xff0c;發布成…

qt筆記(1)——Qtablewidget使用

1.基礎使用方法 &#xff08;略&#xff09; 2.坑和注意點 2.1 設置一個單元格的編輯屬性 在代碼中&#xff0c;想要修改一個單元格的編輯屬性&#xff0c;需要對這個item的flags進行設置&#xff1b;注意對一個tablewidget的一個item成員進行設置后&#xff0c;進行一次編…

字符串的模糊匹配方法介紹

字符串的模糊匹配方法介紹 目錄字符串的模糊匹配方法介紹一、編輯距離&#xff08;Levenshtein Distance&#xff09;復雜度分析二、Jaro-Winkler 距離復雜度分析三、最長公共子序列&#xff08;LCS&#xff09;復雜度分析四、模糊搜索&#xff08;Fuzzy Search&#xff09;復雜…

ActiveMQ在Spring Boot中的詳細使用指南

?? 目錄 ?? ActiveMQ簡介 什么是ActiveMQ? 核心概念 ??? 基礎架構組件 ?? 重要概念解釋 ActiveMQ vs 其他消息中間件 ?? 環境搭建 1. ActiveMQ服務端安裝 Docker方式(推薦初學者) 手動安裝方式 2. 驗證安裝 訪問Web管理界面 連接參數 測試連接 ?…

二元一次方程

前言 最近剛學二元一次方程&#xff0c;想寫一篇專欄熟悉一下本文寫給初一的同學看&#xff0c;學過的就劃了吧二元一次方程 兩個未知數最高項次數為 111 次為整式方程二元一次方程的解不唯一&#xff0c;但是二元一次方程可以用一個未知數來表達另一個未知數eg:eg:eg: xy1x y…

AI編程的未來是智能體原生開發?

目錄 前言 一、從“串行”到“并行”&#xff1a;什么是智能體原生開發&#xff1f; 1.1 傳統模式&#xff08;串行思維&#xff09; 1.2 智能體原生模式&#xff08;并行思維&#xff09; 二、程序員的新角色&#xff1a;從代碼手藝人到系統思想家 三、軟件開發的終局&a…