AQS:全稱AbstractQueueSynchronizer,抽象隊列同步器,這個類在java.util.concurrent.locks包下
它是一個底層同步工具類,比如CountDownLatch,Sammphore,ReentrantLock,ReentrantReadWriteLock等等都是基於AQS
底層三個內容:
1.state(用於計數器)
2.線程標記(哪一個線程加的鎖)
3.阻塞隊列(用於存放阻塞線程)
AQS提供了一種實現阻塞鎖和一系列依賴FIFO等待隊列的同步器的框架,如下圖所示。AQS為一系列同步器依賴於一個單獨的原子變量(state)的同步器提供了一個非常有用的基礎。子類們必須定義改變state變量的protected方法,這些方法定義了state是如何被獲取或釋放的。
J.U.C是基於AQS實現的,AQS是一個同步器,設計模式是模板模式。
核心數據結構:雙向鏈表 + state(鎖狀態)
底層操作:CAS
釋放鎖以及添加線程對於隊列的變化
添加節點
當出現鎖競爭以及釋放鎖的時候,AQS同步隊列中的節點會發生變化,首先看一下添加節點的場景。
這里會涉及到兩個變化
- 新的線程封裝成Node節點追加到同步隊列中,設置prev節點以及修改當前節點的前置節點的next節點指向自己
- 通過CAS講tail重新指向新的尾部節點
釋放鎖移除節點
head節點表示獲取鎖成功的節點,當頭結點在釋放同步狀態時,會喚醒后繼節點,如果后繼節點獲得鎖成功,會把自己設置為頭結點,節點的變化過程如下
這個過程也是涉及到兩個變化
- 修改head節點指向下一個獲得鎖的節點
- 新的獲得鎖的節點,將prev的指針指向null
這里有一個小的變化,就是設置head節點不需要用CAS,原因是設置head節點是由獲得鎖的線程來完成的,而同步鎖只能由一個線程獲得,所以不需要CAS保證,只需要把head節點設置為原首節點的后繼節點,並且斷開原head節點的next引用即可
參考:https://segmentfault.com/a/1190000017372067