前言
CountDownLatch是基于AQS實(shí)現(xiàn)的共享鎖慕淡,用await和countdown方法配合完成其它線程執(zhí)行完,再執(zhí)行阻塞的線程的功能虹蒋。所以這里一些AQS的知識(shí)就不過多的介紹氧秘,詳細(xì)見我的AQS篇章http://www.reibang.com/p/54d372425e54
類結(jié)構(gòu)
public class CountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
}
}
源碼解析
constructor
//構(gòu)造類点晴,實(shí)際上去創(chuàng)建繼承了AbstractQueuedSynchronizer 的Sync類
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
- Sync
Sync(int count) {
//設(shè)置狀態(tài)值,用來計(jì)數(shù)匾荆,當(dāng)?shù)扔?的時(shí)候可以釋放鎖
setState(count);
}
- AQS的setState
protected final void setState(int newState) {
state = newState;
}
await(用來阻塞調(diào)用線程)
public void await() throws InterruptedException {
//調(diào)用的是AQS的acquireSharedInterruptibly方法
sync.acquireSharedInterruptibly(1);
}
- acquireSharedInterruptibly
這個(gè)詳見我的AQS篇章拌蜘,我大概說下流程
判斷是否是中斷標(biāo)志杆烁,是的話直接拋出異常結(jié)束方法了,這樣就取消了資源的獲取简卧,至于異常線程怎么處理咱們這就不用管啦兔魂。如果沒有獲得資源則進(jìn)入阻塞狀態(tài),當(dāng)被喚醒了举娩,是被中斷的狀態(tài)析校,則直接拋出異常結(jié)束自旋方法,當(dāng)然會(huì)進(jìn)入取消獲取節(jié)點(diǎn)階段铜涉,移除自身節(jié)點(diǎn)修改狀態(tài)智玻,并且喚醒下一個(gè)節(jié)點(diǎn)
//這個(gè)詳見我的AQS篇章
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
- tryAcquireShared(CountDownLatch的Sync類對(duì)其進(jìn)行重寫了,只是判斷獲取的狀態(tài)計(jì)數(shù)值芙代,是0則表示獲得資源)
//在Sync類
//嘗試獲取資源(共享鎖)吊奢,當(dāng)狀態(tài)是0代表獲鎖成功
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
countDown(用來釋放相應(yīng)的線程)
//將計(jì)數(shù)狀態(tài)減一
public void countDown() {
sync.releaseShared(1);
}
- releaseShared釋放資源(共享鎖)
//釋放資源(共享鎖)
public final boolean releaseShared(int arg) {
//嘗試獲取共享鎖,在CountDownLatch的內(nèi)部類進(jìn)行重寫
if (tryReleaseShared(arg)) {
//釋放資源,在AQS篇講過了就不做過多解釋了
doReleaseShared();
return true;
}
return false;
}
- tryReleaseShared嘗試獲取共享鎖,在CountDownLatch的內(nèi)部類進(jìn)行重寫
//嘗試獲取共享鎖,在CountDownLatch的內(nèi)部類進(jìn)行重寫
protected boolean tryReleaseShared(int releases) {
//自旋直到狀態(tài)變?yōu)?链蕊,也就是構(gòu)造方法初始化的計(jì)數(shù)狀態(tài)值變?yōu)?后表示獲得鎖
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
如果在理解了AQS的原理以后事甜,看CountDownLatch源碼其實(shí)沒啥東西。
AQS源碼見http://www.reibang.com/p/54d372425e54
覺得還不錯(cuò)的朋友可以點(diǎn)點(diǎn)贊哦L显稀B咔!陪蜻!