AQS概述

AQS概述

AQS 是JUC并發(fā)包中ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier等類的底層實現(xiàn)。
AQS主要是維護了一個CLH阻塞隊列(雙向隊列)


image.png

這個隊列中保存的是沒有獲得鎖的線程。

獲取鎖資源

線程A

ReentrantLock lock = new ReentrantLock(true);
Condition condition = lock.newCondition();

try{
    lock.lock();
    //.....
    condition.await();

 }finally{
    lock.unlock();
 }

具體過程如下:

  • 1.有A,B兩個線程去獲取資源,A線程通過Lock方法獲取鎖資源。
  • 2.B線程接著去調(diào)用Lock方法想獲取已經(jīng)屬于A的鎖資源。
  • 3.B線程會因為獲取鎖失敗(通過CAS操作對狀態(tài)位進行標記來獲取鎖),被封裝成Node節(jié)點放入到AQS CLH雙向隊列中
  • 4.調(diào)用LockSupport.park()將線程阻塞掛起。
  • 5.同理其他再想爭用線程A鎖的線程也會被加入CLH隊列中,并被掛起。

condition

我們知道Lock和synchronized的一大區(qū)別就是Lock支持條件的,Lock和condition的關系是1:n的,即一個lock可以有多個條件

Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
image.png
條件阻塞

Lock和使用condition步驟如下:

  • 1.線程A需要通過lock方法先獲得lock鎖。
  • 2.當線程A調(diào)用到condition.await()釋放鎖(通過CAS操作對狀態(tài)進行標記)
  • 3.阻塞線程A
  • 4.線程A封裝成node節(jié)點放入條件隊列中(每個條件有自己的條件隊列,和AQS的CLH隊列無關)
  • 5.由于資源被釋放,因此去AQS中喚起一個之前被阻塞掛起的線程。
條件釋放
  try
        {
            lock.lock();
           ...
            condition.signal();
        }
        finally
        {
            lock.unlock();
        }
  • 1.已經(jīng)有線程A因為lock的條件被加入到條件隊列,并且被掛起(但是不會將線程加入AQS阻塞隊列,因為條件尚未滿足)。同時線程A釋放lock鎖
  • 2.線程B獲取lock鎖
  • 3.線程B之行condition.signal將原本已經(jīng)因為條件不滿足加入到條件隊列的線程B取出。并將線程B加入到AQS阻塞隊列中
  • 4.當線程B之行unlock操作,阻塞隊列中的線程A可以進行l(wèi)ock的資源爭搶。

AQS概述已經(jīng)講完了,下篇介紹下AQS源碼層面相關。

參考文章

5分鐘入門AQS

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容