CountDownLatch原理分析 - 969251639/study GitHub Wiki
CountDownLatch可以让一个线程设置个卡住点,当CountDownLatch内的线程全部执行玩后这个线程才继续往下走
它的构造方法很简单:
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");//小于0抛出异常
this.sync = new Sync(count);//通过count创造一个同步器
}
另外它的内部用一个同步器Sync来操作线程的通知操作,采用共享锁实现
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {//设置同步状态数量,这里为获取共享锁的数量
setState(count);
}
int getCount() {//返回同步状态的数量
return getState();
}
protected int tryAcquireShared(int acquires) {//尝试获取共享同步状态,如果同步状态数量为0,则表示获取成功,否则失败
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {//释放同步数量
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();//获取同步状态
if (c == 0)//如果同步状态为0,表示没有任何线程占用同步状态,无需释放同步状态,返回false
return false;
int nextc = c-1;//同步状态数量-1
if (compareAndSetState(c, nextc))//cas更新同步数量
return nextc == 0;//如果同步数量减少到0,表示释放成功,反之失败
}
}
}
Sync继承AbstractQueuedSynchronizer,实现它的共享模板方法
https://github.com/969251639/study/wiki/AbstractQueueSysnchorized%E5%8E%9F%E7%90%86
接下来看await的实现
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);//内部的AQS会自动调用tryAcquireShared来尝试获取同步状态
}
protected int tryAcquireShared(int acquires) {//尝试获取共享同步状态,如果同步状态数量为0,则表示获取成功,否则失败
return (getState() == 0) ? 1 : -1;
}
假如CountDownLatch的count为3,那么state的最大值为3,直到调用countDown,将state的值减到0,tryAcquireShared才会返回true
public void countDown() {
sync.releaseShared(1);//内部的AQS会自动调用tryReleaseShared来尝试释放同步状态
}
protected boolean tryReleaseShared(int releases) {//释放同步数量
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();//获取同步状态
if (c == 0)//如果同步状态为0,表示没有任何线程占用同步状态,无需释放同步状态,返回false
return false;
int nextc = c-1;//同步状态数量-1
if (compareAndSetState(c, nextc))//cas更新同步数量
return nextc == 0;//如果同步数量减少到0,表示释放成功,反之失败
}
}