Java中AQS原理

一、核心架構:AQS抽象隊列同步器


二、AQS核心機制

1. 三大核心組件:

  • state狀態變量:volatile int,表示鎖狀態(0=未鎖定,≥1=鎖定/重入次數)

  • CLH隊列:雙向鏈表實現的線程等待隊列

  • Node節點:封裝等待線程和狀態(包含:CANCELLED/SIGNAL/CONDITION/PROPAGATE)

2. 關鍵狀態值:

// Node狀態常量
static final int CANCELLED =  1;  // 線程已取消
static final int SIGNAL    = -1;  // 后繼線程需要喚醒
static final int CONDITION = -2;  // 在條件隊列等待
static final int PROPAGATE = -3;  // 共享模式下傳播喚醒

三、ReentrantLock工作流程

1. 獲取鎖(lock()):

2. 釋放鎖(unlock()):


四、公平鎖 vs 非公平鎖實現差異

1. 非公平鎖(默認)

final boolean nonfairTryAcquire(int acquires) {// 直接嘗試獲取鎖(可能插隊)if (c == 0 && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}// 檢查重入else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;setState(nextc);return true;}return false;
}

2. 公平鎖

protected final boolean tryAcquire(int acquires) {// 先檢查隊列是否有等待線程if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}// 重入邏輯相同
}

五、AQS關鍵方法解析
方法作用
tryAcquire(int)嘗試獲取鎖(需子類實現)
tryRelease(int)嘗試釋放鎖(需子類實現)
acquireQueued()線程加入隊列后自旋獲取鎖
shouldParkAfterFailedAcquire()檢查是否應該阻塞線程
unparkSuccessor()喚醒后繼節點線程
compareAndSetState()CAS更新state值(保證原子性)

六、問題總結

Q:ReentrantLock如何基于AQS實現?

A:
ReentrantLock的核心實現依賴于AQS框架:

  1. 狀態管理

    • 使用AQS的state變量記錄鎖狀態(0=未鎖定,≥1=重入次數)

    • 通過compareAndSetState()保證原子更新

  2. 線程排隊

    • 獲取鎖失敗的線程被封裝為Node加入CLH隊列

    • 隊列基于雙向鏈表實現(FIFO)

  3. 鎖獲取流程

    • 先嘗試tryAcquire()直接獲取鎖

    • 失敗后調用addWaiter()加入隊列尾部

    • 在隊列中自旋檢查前驅節點狀態

    • 最終通過LockSupport.park()阻塞線程

  4. 鎖釋放流程

    • 調用tryRelease()減少重入計數

    • 當state歸零時,調用unparkSuccessor()喚醒隊首線程

    • 被喚醒線程重新嘗試獲取鎖

  5. 公平性實現

    • 公平鎖:先檢查隊列是否有等待線程(hasQueuedPredecessors()

    • 非公平鎖:允許插隊直接嘗試獲取鎖

Q:AQS為什么使用CLH隊列?

A:
CLH隊列(Craig, Landin, and Hagersten鎖)的優勢:

  1. 無鎖入隊:通過CAS操作實現線程安全入隊

  2. 低競爭:每個線程只監控前驅節點狀態

  3. 高效喚醒:只需修改前驅節點的狀態即可喚醒后繼線程

  4. 適應性:完美支持超時、中斷等復雜場景

Q:ReentrantLock如何基于AQS實現?

A:
ReentrantLock的核心實現依賴于AQS框架,未獲取鎖的線程會被完全阻塞

  1. 阻塞時機:當線程嘗試獲取鎖失敗,且自旋檢查后仍無法獲取時

  2. 阻塞方式

    • 調用LockSupport.park()方法使線程進入WAITING狀態

    • 線程釋放CPU資源,不再消耗計算周期

    • 線程狀態變為WAITING (parking)

  3. 阻塞位置

    • 線程在CLH隊列中排隊等待

    • 每個線程監控前驅節點的狀態

  4. 喚醒機制

    • 前驅節點釋放鎖時調用unparkSuccessor()

    • 通過LockSupport.unpark()精確喚醒后繼線程

    • 喚醒后線程重新嘗試獲取鎖

  5. 與忙等待的區別

    • 不同于忙等待(while循環),park()會使線程讓出CPU

    • 避免空轉消耗CPU資源

    • 通過操作系統級同步原語實現高效阻塞/喚醒


七、進階問題問題
  1. state變量為什么用volatile?

    • 保證多線程間的可見性

    • 確保鎖狀態變化能被立即感知

    • 配合CAS實現無鎖狀態更新

  2. 如何處理鎖重入?

    // 獲取鎖時檢查當前線程是否是持有者
    if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;setState(nextc); // 增加重入計數return true;
    }
  3. 為什么喚醒后繼節點而不是所有線程?

    • 減少不必要的線程喚醒(驚群效應)

    • 保證公平性(FIFO順序)

    • 提高系統吞吐量

  4. AQS如何支持超時機制?

    public final boolean tryAcquireNanos(int arg, long nanosTimeout) {if (Thread.interrupted()) throw new InterruptedException();return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout); // 超時獲取
    }
    • 在自旋過程中檢查超時時間

    • 超時后標記節點為CANCELLED

  5. 為什么非公平鎖性能更高?

    • 減少線程切換開銷(新線程可直接搶鎖)

    • 避免喚醒延遲(CLH隊列喚醒需要時間)

    • 但可能導致線程饑餓


總結:AQS設計精髓

  1. 模板方法模式:定義骨架流程(acquire/release),子類實現關鍵操作(tryAcquire/tryRelease)

  2. 無鎖算法:通過CAS實現安全的狀態更新

  3. 等待隊列:優雅管理阻塞線程

  4. 可擴展性:支持獨占/共享兩種模式

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

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

相關文章

深入理解程序鏈接機制:靜態鏈接、ELF加載與動態庫實現原理

目錄 一、靜態鏈接 1、靜態鏈接的基本概念 1. 靜態鏈接實例分析 2. 目標文件分析 3. 關鍵觀察 4. 重定位機制 5. 注意事項 2、靜態鏈接過程詳解 1. 目標文件反匯編分析(上面已分析) 2. 符號表分析 code.o 符號表 hello.o 符號表 3. 鏈接后的…

python基礎復習

復習python基礎語法,最好能做到使用python 寫一些簡單的算法。 1基礎基礎語法 1.0 輸入輸出 一個實用的print:format函數print(站點列表 {0}, {1}, 和 {other}。.format(Google, Runoob, other=Taobao)) 站點列表 Google, Runoob, 和 Taobao。print("a", "b…

ZLMediaKit 入門

什么是ZLMediaKit? ZLMediaKit 是一個基于C11的高性能流媒體服務器框架,支持RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV等多種流媒體協議。它具有以下特點: 跨平臺支持(Linux、Windows、macOS) 高性能,支持高…

接口測試Postman工具高級使用技巧

目錄 一、環境與變量的深度應用 多環境動態切換 動態變量與腳本生成 二、Pre-request Script 的妙用 參數簽名/加密 接口依賴處理 三、Test Script 的進階斷言 復雜 JSON Schema 校驗 數據庫斷言 四、數據驅動測試 CSV/JSON 文件驅動 動態生成測試用例 環境與變量的…

ZooKeeper學習專欄(四):單機模式部署與基礎操作詳解

文章目錄前言一、單機模式部署架構圖部署流程:二、zkCli.sh命令行工具基礎操作三、ACL權限控制實踐學習資源前言 本文是Zookeeper學習系列的第四篇,將詳細講解Zookeeper的單機模式部署過程以及基礎命令行操作,包括節點管理、Watcher機制和AC…

靜態登錄界面

代碼&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>用戶登錄</title><st…

Three.js 全景圖(Equirectangular Texture)教程:從加載到球面映射

全景圖(Equirectangular Texture)是一種特殊的 2D 圖像,能通過數學轉換模擬 360 環繞視角,常用于創建沉浸式環境(如虛擬全景、天空盒替代方案)。本文將通過完整示例,帶你掌握 Three.js 中全景圖的加載、映射原理與實際應用。 什么是全景圖(Equirectangular Texture)?…

Rocky Linux 9 快速安裝 Node.js

Rocky Linux 9 快速安裝 Node.js 大家好&#xff0c;我是星哥&#xff01;今天給大家帶來 Rocky Linux 9 環境下 Node.js 的安裝教程。 本文將詳細介紹兩種安裝方法&#xff0c;幫你快速搭建穩定的 Node.js 環境。 Node.js 是一個非常流行的 JavaScript 運行時環境&#xff…

.NET依賴注入IOC你了解嗎?

IOC在Web API 中是經常使用的&#xff0c;但是在一些WPF項目并不是經常使用或者被人熟知的&#xff0c;我把相關依賴注入的內容又做了一次學習和整理什么是依賴注入&#xff1f; 依賴注入是一種設計模式和軟件設計原則&#xff0c;用于實現 控制反轉。它的核心思想是&#xff1…

Python----大模型(基于Fastapi+streamlit的機器人對話)

一、準備工作 1.1、魔搭社區下載大模型 通義千問2.5-7B-Instruct 模型庫 from modelscope.hub.snapshot_download import snapshot_download llm_model_dir snapshot_download(Qwen/Qwen2.5-7B-Instruct,cache_dirmodels) 1.2、啟動vllm大模型 python -m vllm.entrypoint…

前端面試專欄-工程化:29.微前端架構設計與實踐

&#x1f525; 歡迎來到前端面試通關指南專欄&#xff01;從js精講到框架到實戰&#xff0c;漸進系統化學習&#xff0c;堅持解鎖新技能&#xff0c;祝你輕松拿下心儀offer。 前端面試通關指南專欄主頁 前端面試專欄規劃詳情 微前端架構設計與實踐 一、微前端核心概念與價值 …

Spring Boot音樂服務器項目-上傳音樂模塊

項目結構圖 相較于上次新增集中在這些地方&#xff1a; &#x1f680; 上傳音樂的核心流程 前端投遞&#xff1a;用戶填寫歌手名 選擇MP3文件 后端接收&#xff1a;/music/upload 接口化身音樂快遞員 安全驗證&#xff1a;先查用戶是否“持證上崗”&#xff08;登錄態&#…

2025年遠程桌面軟件深度評測:ToDesk、向日葵、TeamViewer全方位對比分析

隨著遠程辦公和數字化協作的深入發展&#xff0c;遠程桌面軟件已經成為個人用戶和企業的必備工具。在2025年的今天&#xff0c;遠程控制軟件市場呈現出百花齊放的態勢&#xff0c;其中ToDesk、向日葵和TeamViewer作為市場上的三大主流選擇&#xff0c;各自在技術創新、性能優化…

深度學習-全連接神經網絡2

六、反向傳播算法 反向傳播&#xff08;Back Propagation&#xff0c;簡稱BP&#xff09;算法是用于訓練神經網絡的核心算法之一&#xff0c;它通過計算損失函數&#xff08;如均方誤差或交叉熵&#xff09;相對于每個權重參數的梯度&#xff0c;來優化神經網絡的權重。 1、前…

C語言的歷史

C 語言是一種 通用的、過程式的編程語言&#xff0c;由 丹尼斯里奇&#xff08;Dennis Ritchie&#xff09; 在 1972 年于貝爾實驗室開發。它以 高效、靈活、貼近硬件 而著稱&#xff0c;廣泛應用于系統軟件、嵌入式系統、驅動程序、游戲引擎、數據庫系統等底層開發領域。 C語…

jupyter使用

啟動win rcmdjupyter notebook創建python文件

linux 環境服務發生文件句柄泄漏導致服務不可用

問題描述&#xff1a;服務調用遠程rest接口 報錯&#xff0c;發生too many open files 異常&#xff0c;系統句柄資源耗盡&#xff0c;導致服務不可用。排查經過&#xff1a;1、針對報錯代碼進行本地構建&#xff0c;構造異常&#xff0c;并進行壓測。問題未復現2、經過討論分析…

手機錄制視頻時,硬編碼和軟編碼哪個質量高?(硬件編碼、軟件編碼)

文章目錄**1. 畫質對比**- **軟編碼**&#xff1a;- **硬編碼**&#xff1a;**2. 性能與功耗**- **軟編碼**&#xff1a;- **硬編碼**&#xff1a;**3. 實際應用中的權衡****4. 現代手機的折中方案****5. 如何選擇&#xff1f;****總結**在手機錄制視頻時&#xff0c; 軟編碼的…

IPv4與IPv6雙棧協議:網絡過渡的關鍵技術

為什么需要IPv4與IPv6共存&#xff1f; 在網絡技術的世界中&#xff0c;兼容性問題始終是最大的挑戰之一。IPv4和IPv6之間存在根本性的不兼容性&#xff0c;這意味著使用不同協議的設備無法直接通信。這種情況就像是兩個人試圖用完全不同的語言進行對話一樣。 目前的網絡現狀…

【牛客刷題】數字變換

一、題目描述 給出兩個數字a,ba,ba,b,aaa每次可以乘上一個大于1的正整數得到新的aa