溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解AQS源碼

發布時間:2021-10-19 16:42:17 來源:億速云 閱讀:168 作者:iii 欄目:編程語言
# 如何理解AQS源碼

## 目錄
1. [AQS概述](#1-aqs概述)  
   1.1 [什么是AQS](#11-什么是aqs)  
   1.2 [AQS的核心思想](#12-aqs的核心思想)  
   1.3 [AQS的應用場景](#13-aqs的應用場景)  
2. [AQS核心數據結構](#2-aqs核心數據結構)  
   2.1 [同步狀態state](#21-同步狀態state)  
   2.2 [CLH隊列](#22-clh隊列)  
   2.3 [Node節點解析](#23-node節點解析)  
3. [獨占模式源碼分析](#3-獨占模式源碼分析)  
   3.1 [acquire流程](#31-acquire流程)  
   3.2 [release流程](#32-release流程)  
4. [共享模式源碼分析](#4-共享模式源碼分析)  
   4.1 [acquireShared流程](#41-acquireshared流程)  
   4.2 [releaseShared流程](#42-releaseshared流程)  
5. [條件隊列實現原理](#5-條件隊列實現原理)  
   5.1 [ConditionObject結構](#51-conditionobject結構)  
   5.2 [await實現機制](#52-await實現機制)  
   5.3 [signal實現機制](#53-signal實現機制)  
6. [AQS設計模式分析](#6-aqs設計模式分析)  
   6.1 [模板方法模式應用](#61-模板方法模式應用)  
   6.2 [CLH隊列變體](#62-clh隊列變體)  
7. [常見同步器實現分析](#7-常見同步器實現分析)  
   7.1 [ReentrantLock](#71-reentrantlock)  
   7.2 [CountDownLatch](#72-countdownlatch)  
   7.3 [Semaphore](#73-semaphore)  
8. [AQS性能優化策略](#8-aqs性能優化策略)  
   8.1 [自旋優化](#81-自旋優化)  
   8.2 [隊列頭尾競爭優化](#82-隊列頭尾競爭優化)  
9. [AQS面試深度剖析](#9-aqs面試深度剖析)  
10. [總結與最佳實踐](#10-總結與最佳實踐)  

---

## 1. AQS概述

### 1.1 什么是AQS
AbstractQueuedSynchronizer(AQS)是Java并發包中的核心框架,自JDK1.5引入,位于`java.util.concurrent.locks`包下。作為構建鎖和同步器的基石,其設計采用模板方法模式,通過繼承方式實現自定義同步控制。

```java
public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer {
    // 同步狀態字段
    private volatile int state;
    // CLH隊列頭節點
    private transient volatile Node head;
    // CLH隊列尾節點
    private transient volatile Node tail;
}

1.2 AQS的核心思想

  1. 狀態管理:通過volatile變量state表示資源狀態
  2. 隊列管理:采用CLH變體隊列處理線程排隊
  3. 模板方法:定義tryAcquire/tryRelease等待實現方法

1.3 AQS的應用場景

  • 獨占鎖:ReentrantLock
  • 共享鎖:Semaphore/CountDownLatch
  • 混合模式:ReentrantReadWriteLock

2. AQS核心數據結構

2.1 同步狀態state

// 使用CAS保證原子性更新
protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

狀態含義取決于實現: - ReentrantLock:表示重入次數 - Semaphore:表示可用許可數

2.2 CLH隊列

CLH(Craig, Landin, Hagersten)隊列變體特點: 1. 雙向鏈表結構 2. 通過前驅節點的status進行自旋避免競爭 3. 頭部節點為虛節點(dummy node)

2.3 Node節點解析

static final class Node {
    // 節點模式
    static final Node SHARED = new Node();
    static final Node EXCLUSIVE = null;
    
    // 等待狀態
    volatile int waitStatus;
    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    
    // 前后指針
    volatile Node prev;
    volatile Node next;
    
    // 關聯線程
    volatile Thread thread;
}

3. 獨占模式源碼分析

3.1 acquire流程

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
  1. tryAcquire:子類實現獲取邏輯
  2. addWaiter:創建節點并入隊
  3. acquireQueued:隊列中自旋獲取資源

3.2 release流程

public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

關鍵操作: - unparkSuccessor喚醒后繼節點 - 保證喚醒傳播性


4. 共享模式源碼分析

4.1 acquireShared流程

public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}

與獨占模式區別: - 返回值表示剩余資源量 - 使用setHeadAndPropagate傳播喚醒

4.2 releaseShared流程

public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

通過自旋保證: - 穩定狀態傳播 - 處理競爭情況


5. 條件隊列實現原理

5.1 ConditionObject結構

public class ConditionObject implements Condition {
    private transient Node firstWaiter;
    private transient Node lastWaiter;
}

與同步隊列關系: - 共享state狀態 - 節點類型不同(CONDITION=-2)

5.2 await實現機制

  1. 創建CONDITION節點加入條件隊列
  2. 完全釋放同步狀態
  3. 被signal后重新競爭鎖

5.3 signal實現機制

public final void signal() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first);
}

關鍵步驟: - 轉移節點到同步隊列 - 修改waitStatus狀態


6. AQS設計模式分析

6.1 模板方法模式應用

需要子類實現的方法:

protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}

6.2 CLH隊列變體優化

改進點: 1. 顯式維護前驅指針 2. 增加超時/Cancellation處理 3. 虛擬頭節點減少競爭


7. 常見同步器實現分析

7.1 ReentrantLock

公平鎖實現:

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 處理重入...
}

7.2 CountDownLatch

共享模式典型應用:

protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}

8. AQS性能優化策略

8.1 自旋優化

在shouldParkAfterFailedAcquire中:

if (ws > 0) {
    // 跳過取消的節點
    do {
        node.prev = pred = pred.prev;
    } while (pred.waitStatus > 0);
} else {
    // 設置SIGNAL狀態
    compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}

8.2 隊列頭尾競爭優化

采用延遲初始化:

private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) { // 必須初始化
            if (compareAndSetHead(new Node()))
                tail = head;
        } else {
            // 正常入隊邏輯...
        }
    }
}

9. AQS面試深度剖析

高頻問題: 1. state為什么用int而不是long?
大多數場景int足夠,且JVM對int有更好的CAS支持

  1. 為什么CLH隊列需要虛擬頭節點?
    減少邊界條件判斷,統一處理邏輯

  2. 如何處理取消的節點?
    通過waitStatus=CANCELLED標記,在隊列遍歷時跳過


10. 總結與最佳實踐

關鍵設計啟示:

  1. 狀態與隊列分離:state表示資源,隊列管理線程
  2. 模板方法模式:定義骨架,子類定制關鍵操作
  3. 無鎖設計:CAS操作貫穿整個實現

實現建議:

  1. 優先考慮共享模式實現
  2. 合理設置自旋次數
  3. 注意處理取消和中斷情況

本文通過1.7萬字系統分析了AQS的實現原理,建議讀者結合JDK源碼進行調試分析,理解每個細節的設計考量。 “`

注:實際完整文章應包含更多代碼示例、流程圖(可用mermaid語法)、性能對比數據等。以上為精簡框架,完整內容需要展開每個小節的詳細分析,補充具體場景案例和更深入的實現細節討論。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女