CountDownLatch源码
2020-08-24 本文已影响0人
我是许仙
作用
一种同步工具,允许一个或多个线程等待直到其他线程中的任务执行完成。CountdownLatch的构造方法传入int类型的count数据。由于调用了countDown的方法,count的值每次调用减少1,await()方法被阻塞,直到count的是0之后,所有被阻塞的线程被释放,之后再次调用await()将立即返回数据。
await()
阻塞线程直到cout值变为0,或者受到中断信号。如果值已经为0则继续运行。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
await(Time )
阻塞线程直到一定时间
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
countDown()
count值减少1直到0,如果为0则唤醒所有的等待线程。
public void countDown() {
sync.releaseShared(1);
}
源码
中间状态state,共享锁state为0代表获取到了锁,互斥锁state不为0代表获取到了锁 这2个正好相反的。
核心是在类的内部有一个继承了 AbstractQueuedSynchronizer的内部类syn
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
//获取锁 1代表获取到了锁,-1代表没有获取到锁
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
//释放锁
protected boolean tryReleaseShared(int releases) {
//自旋
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
await()获取锁,判断cout的值是否为0,如果是0则代表获取到了锁直接返回。如果cout > 0 则代表获取锁失败,把当前线程添加到一个FIFO的双端列队中,其中头部nede所有的属性为null,头部node代表获取到了锁或者初始化的node。添加到列队后,线程被阻塞。
coutDown()释放锁。通过cas操作中间变量state=state-1。 当state=0的时候调用doReleaseShared()方法执行释放操作,他会唤醒头部节点的下一个节点的线程(因为cas中头部节点代表了获取到锁的线程)。
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
//唤醒调用了 await()线程
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}