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;
}
流程图
image-20200824185211535.png
上一篇下一篇

猜你喜欢

热点阅读