美文网首页
JUC原理之CountDownLatch

JUC原理之CountDownLatch

作者: AlienPaul | 来源:发表于2020-03-19 11:48 被阅读0次

    什么是CountDownLatch

    CountDownLatch为一个多线程协调辅助工具。一句话描述是当n个线程都进行完工作之后,再通知另一组已阻塞的线程恢复执行。

    使用方法

    CountDownLatch的构造函数中需要指定参数n。

    CountDownLatch latch = new CountDownLatch(n);
    

    需要等待其他线程工作的线程需要调用:

    latch.await();
    

    工作线程任务执行完之后调用:

    latch.countDown();
    

    一旦countDown方法累计调用满n次,所有阻塞在await方法的线程会恢复执行。

    注意:CountDownLatch的计数n是无法重置的。一旦创建完成只能通过countDown方法递减。如果需要重新设置n值,需要创建新的CountDownLatch

    countDown方法的实现

    ReentrantLock一样,CountDownLatch内部也有一个Sync,继承自AQS。

    CountDownLatch基于共享锁的方式来实现,这个在后面介绍。

    countDown方法调用的是释放共享锁的逻辑。代码如下:

    public void countDown() {
        sync.releaseShared(1);
    }
    

    await方法

    await方法调用的是获取共享锁的逻辑,代码如下:

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    

    Sync类

    CountDownLatch的重点逻辑位于Sync类中。

    ReentrantLock不同,CountDownLatchSync初始化时候的state已经被设置为n。接下来每次调用countDown的时候通过CAS将state减去1。所有调用await的线程会对比state的值,只有state为0的时候,才允许执行,否则一律阻塞。

    Sync类的代码和相关解释如下所示:

    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;
    
        // 创建CountDownLatch时候设置初始的state值
        Sync(int count) {
            setState(count);
        }
    
        int getCount() {
            return getState();
        }
    
        // await方法调用。await方法获取共享锁
        // 如果state状态为0,说明有state个线程执行了countDown方法,此时唤醒所有的await线程
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
    
        // countDown方法调用,释放共享锁
        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            // 自旋
            for (;;) {
                int c = getState();
                // 如果已经有state个线程执行过countDown,返回false
                if (c == 0)
                    return false;
                // state减一
                int nextc = c-1;
                // CAS设置state
                // 只有nextc为0的时候返回true,唤醒await阻塞的线程
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }
    

    本文为原创内容,欢迎大家讨论、批评指正与转载。转载时请注明出处。

    相关文章

      网友评论

          本文标题:JUC原理之CountDownLatch

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