Java 并发总结——AQS
一、AQS
Java并發包(JUC)中提供了很多并發工具,ReentrangLock、Semaphore、CountDownLatch,它們的實現都用到了一個共同的基類——AbstractQueuedSynchronizer,簡稱AQS。
AQS是一個用來構建鎖和同步器的框架,使用AQS能簡單且高效地構造出應用廣泛的大量的同步器,比如我們提到的ReentrantLock,Semaphore,其他的諸如ReentrantReadWriteLock,SynchronousQueue,FutureTask等皆是基于AQS的
二、基本實現原理
AQS維護一個共享資源state,通過內置的FIFO來完成獲取資源線程的排隊工作。該隊列由一個一個的Node結點組成,每個Node結點維護一個prev引用和next引用,分別指向自己的前驅和后繼結點,雙端雙向鏈表。
private volatile int state;//共享變量,使用volatile修飾保證線程可見性
狀態信息通過procted類型的getState,setState,compareAndSetState進行操作
三、AQS兩種同步方式
獨占式、共享式
獨占式如ReentrantLock
共享式如Semaphore,CountDownLatch,
組合式的如ReentrantReadWriteLock
(1)獨占式
acquire
a.首先tryAcquire獲取同步狀態,成功則直接返回;否則,進入下一環節;
b.線程獲取同步狀態失敗,就構造一個結點,加入同步隊列中,這個過程要保證線程安全;
c.加入隊列中的結點線程進入自旋狀態,若是老二結點(即前驅結點為頭結點),才有機會嘗試去獲取同步狀態;否則,當其前驅結點的狀態為SIGNAL,線程便可安心休息,進入阻塞狀態,直到被中斷或者被前驅結點喚醒。
release
release的同步狀態相對簡單,需要找到頭結點的后繼結點進行喚醒,若后繼結點為空或處于CANCEL狀態,從后向前遍歷找尋一個正常的結點,喚醒其對應線程。
(2)共享式
共享式地獲取同步狀態,同步狀態的方法tryAcquireShared返回值為int。
a.當返回值大于0時,表示獲取同步狀態成功,同時還有剩余同步狀態可供其他線程獲取;
b.當返回值等于0時,表示獲取同步狀態成功,但沒有可用同步狀態了;
c.當返回值小于0時,表示獲取同步狀態失敗。
(3)模板方法模式
protected boolean tryAcquire(int arg) : 獨占式獲取同步狀態,試著獲取,成功返回true,反之為false
protected boolean tryRelease(int arg) :獨占式釋放同步狀態,等待中的其他線程此時將有機會獲取到同步狀態;
protected int tryAcquireShared(int arg) :共享式獲取同步狀態,返回值大于等于0,代表獲取成功;反之獲取失敗;
protected boolean tryReleaseShared(int arg) :共享式釋放同步狀態,成功為true,失敗為false
(5)雙向鏈表Node節點的狀態
CANCELLED,值為1,表示當前的線程被取消;
SIGNAL,值為-1,表示當前節點的后繼節點包含的線程需要運行,也就是unpark;
CONDITION,值為-2,表示當前節點在等待condition,也就是在condition隊列中;
PROPAGATE,值為-3,表示當前場景下后續的acquireShared能夠得以執行;
值為0,表示當前節點在sync隊列中,等待著獲取鎖。
(6)AQS實現公平鎖和非公平鎖
非公平鎖中,那些嘗試獲取鎖且尚未進入等待隊列的線程會和等待隊列head結點的線程發生競爭。
公平鎖中,在獲取鎖時,增加了isFirst(current)判斷,當且僅當,等待隊列為空或當前線程是等待隊列的頭結點時,才可嘗試獲取鎖。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Java 并发总结——AQS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 并发总结——进程与线程
- 下一篇: Java 证书pem转KeyStore、