掌握高併發、高可用架構
第二課 併發編程
從本課開始學習併發編程的內容。主要介紹併發編程的基礎知識、鎖、內存模型、線程池、各種併發容器的使用。
第五節 AQS和ReadWriteLock
併發編程
線程通信
AQS
ReadWriteLock
Lock
AQS:AbstractQueuedSynchronizer
在同步組件的實現過程中,AQS是核心部分,通過使用AQS的模板方法來實現同步語義。AQS包含同步隊列的定義,以及對同步隊列進行排隊、等待通知等來實現的獨佔鎖的獲取和釋放;共享鎖的獲取和釋放;可中斷鎖;超時等待鎖等特性。
同步隊列,即內部類Node
volatile int waitState; // 節點狀態
volatile Node prev; // 當前節點的上一節點
volatile Node next; // 當前節點的下一節點
volatile Thread thread; // Node主體,線程
Node nextWaiter; // 等待隊列中的下一節點
其中,節點狀態的取值範圍爲:
int CANCELLED = 1; // 節點從隊列中取消
int INITIAL = 0; // 初始狀態
int SIGNAL = -1; // 下一節點處於等待狀態,噹噹前線程釋放鎖後會通知下一節點,使其進入執行狀態
int CONDITION = -2; // 當前節點進入等待狀態
int PROPAGATE = -3; // 表示下一次共享狀態獲取將會無條件傳播下去
顯然,同步隊列是一個雙向鏈表。
另外,AQS中有兩個很重要的變量:同步隊列的頭尾節點。
private transient volatile Node head;
private transient volatile Node tail;
AQS通過頭尾指針來管理同步隊列,同時實現包括獲取鎖失敗的線程進入隊列、釋放鎖時對同步隊列進行通知等核心功能。
獨佔鎖
void acquire(int arg); //獨佔式獲取同步鎖,如果獲取失敗則插入同步隊列進行等待
void acquireInterruptibly(int arg); //與acquire相同,但在同步隊列等待過程中可響應中斷
boolean tryAcquireNanos(int arg, long nanos); //在acquireInterruptibly的基礎上增加了超時等待的功能,在超時時間內沒有獲取到同步鎖則返回false
boolean release(int arg); //釋放鎖,該方法會喚醒同步隊列中的下一個節點
共享鎖
void acquireShared(int arg); //共享式獲取同步鎖,與獨佔鎖的區別是同一時刻可以有多個線程獲取到同步狀態
void acquireSharedInterruptibly(int arg); //在acquireShared基礎上增加了響應中斷的功能
boolean tryAcquireSharedNanos(int arg, long nanos); //在acquireSharedInterruptibly的基礎上增加了超時等待的功能
boolean releaseShared(int arg); //釋放共享式鎖