高並發編程-AQS深入解析

高並發編程-AQS深入解析

要點解說

AbstractQueuedSynchronizer簡稱AQS,它是java.util.concurrent包下CountDownLatch/FutureTask/ReentrantLock/RenntrantReadWriteLock/Semaphore實現的基礎,所以深入理解AQS非常有必要。

AQS通過內部實現的FIFO等待隊列來完成資源獲取線程的等待工作,如果當前線程獲取資源失敗,AQS則會將當前線程以及等待狀態等信息構造成一個Node結構的節點,並將其加入等待隊列中,同時會阻塞當前線程;當其它獲取到資源的線程釋放持有的資源時,則會把等待隊列節點中的線程喚醒,使其再次嘗試獲取對應資源。

源碼解析

AbstractQueuedSynchronizer源碼比較長,這裡只分析主要的功能代碼。首先,先看一下它內部定義的Node類的代碼。

static final class Node { //聲明共享模式下的等待節點 static final Node SHARED = new Node(); //聲明獨佔模式下的等待節點 static final Node EXCLUSIVE = null; //waitStatus的一常量值,表示線程已取消 static final int CANCELLED = 1; //waitStatus的一常量值,表示後繼線程需要取消掛起 static final int SIGNAL = -1; //waitStatus的一常量值,表示線程正在等待條件 static final int CONDITION = -2; //waitStatus的一常量值,表示下一個acquireShared應無條件傳播 static final int PROPAGATE = -3; //waitStatus,其值只能為CANCELLED、SIGNAL、CONDITION、PROPAGATE或0 //初始值為0 volatile int waitStatus; //前驅節點 volatile Node prev; //後繼節點 volatile Node next; //當前節點的線程,在節點初始化時賦值,使用後為null volatile Thread thread; //下一個等待節點 Node nextWaiter; Node() { } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } }

上面的Node就是等待隊列里的一個節點,具體結構如下:

接著,來看一下AbstractQueuedSynchronizer的三個重要屬性:

//等待隊列的頭結點 private transient volatile Node head; //等待隊列的尾節點 private transient volatile Node tail; //同步狀態,這個很重要 private volatile int state;

從這就可以得到同步隊列的基本結構:

同時,同步器中提供了三個方法用於操作同步狀態:

protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } //使用CAS設置同步狀態,確保線程安全 protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); }

AbstractQueuedSynchronizer類中其它方法主要是用於插入節點、釋放節點,插入節點過程如下圖所示:

釋放頭結點過程如下圖所示:

分析小結

AbstractQueuedSynchronizer實現了對資源獲取與釋放的基礎實現,真正使用到的地方還在是各個具體的功能類中,如CountDownLatch、ReentrantLock等,後面在這些類中會具體分析。

面試考點

AQS是什麼?內部實現結構了解嗎?

AbstractQueuedSynchronizer簡稱AQS,它為實現依賴於先進先出 (FIFO) 等待隊列的阻塞鎖和相關同步器(信號量等)提供一個基礎實現框架。內部實現結構參考上面的圖示作答。

推薦閱讀:

golang簡單key/value資料庫(二)
高並發和高性能系統中進程、線程、協程、隊列的詳解,以及各運行模式的對比
Python操作rabbitmq系列(三):多個接收端消費消息
性能測試筆記(一):吞吐量與並發數
Go並發調度器解析之實現一個協程池

TAG:並發 | 系統架構 | 高並發 |