當前位置:首頁 >
這都可以?(aqs有限公司)aqs原理,
AQS概述
AQS 是JUC并發包中ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier等類的底層實現。
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線程接著去調用Lock方法想獲取已經屬于A的鎖資源。3.B線程會因為獲取鎖失敗(通過CAS操作對狀態位進行標記來獲取鎖),被封裝成Node節點放入到AQS CLH雙向隊列中4.調用LockSupport.park()將線程阻塞掛起。5.同理其他再想爭用線程A鎖的線程也會被加入CLH隊列中,并被掛起。condition
我們知道Lock和synchronized的一大區別就是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調用到condition.await()釋放鎖(通過CAS操作對狀態進行標記)3.阻塞線程A4.線程A封裝成node節點放入條件隊列中(每個條件有自己的條件隊列,和AQS的CLH隊列無關)5.由于資源被釋放,因此去AQS中喚起一個之前被阻塞掛起的線程。條件釋放
try
{
lock.lock();
...
condition.signal();
}
finally
{
lock.unlock();
}
1.已經有線程A因為lock的條件被加入到條件隊列,并且被掛起(但是不會將線程加入AQS阻塞隊列,因為條件尚未滿足)。同時線程A釋放lock鎖2.線程B獲取lock鎖3.線程B之行condition.signal將原本已經因為條件不滿足加入到條件隊列的線程B取出。并將線程B加入到AQS阻塞隊列中4.當線程B之行unlock操作,阻塞隊列中的線程A可以進行lock的資源爭搶。AQS概述已經講完了,下篇介紹下AQS源碼層面相關。