美文网首页
CountDownLatch源码

CountDownLatch源码

作者: 我是许仙 | 来源:发表于2020-08-24 18:56 被阅读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

    相关文章

      网友评论

          本文标题:CountDownLatch源码

          本文链接:https://www.haomeiwen.com/subject/xjhdjktx.html