JUC源码分析-JUC锁(三):CountDownLatch

1. 概述

CountDownLatch是一个同步辅助类,通过AQS实现的一个闭锁。在其他线程完成它们的操作之前,允许一个多个线程等待。简单来说,CountDownLatch中有一个锁计数,在计数到达0之前,线程会一直等待。

《JUC源码分析-JUC锁(三):CountDownLatch》

CountDownLatch运行机制

2. 数据结构和核心参数

 

《JUC源码分析-JUC锁(三):CountDownLatch》

CountDownLatch继承关系

从锁类别来说,CountDownLatch是一个“共享锁”,内部定义了自己的同步器Sync,Sync继承自AQS,实现了tryAcquireSharedtryReleaseShared两个方法。需要注意的是,CountDownLatch中的锁是响应中断的,如果线程在对锁进行操作期间发生中断,会直接抛出InterruptedException

 

3. 源码解析

//构造函数
public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}
//CountDownLatch中的计数其实就是AQS的state
Sync(int count) {
    setState(count);
}

说明:从构造函数中可以看出,CountDownLatch的“锁计数”本质上就是AQS的资源数state。下面我们将通过await()countDown()两个方法来分析CountDownLatch的“latch”实现。

3.1 await()

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

//AQS中acquireSharedInterruptibly(1)的实现
public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}

//tryAcquireShared在CountDownLatch中的实现
protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}

说明:await()的实现非常简单,就是通过对资源state剩余量(state==0 ? 1 : -1)来判断是否获取到锁。在《AQS》篇中我们讲到过,tryAcquireShared函数规定了它的返回值类型:成功获取并且还有可用资源返回正数;成功获取但是没有可用资源时返回0;获取资源失败返回一个负数。 也就是说,只要state!=0,线程就进入等待队列阻塞。

3.2 countDown()

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

//AQS中releaseShared(1)的实现
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();//唤醒后续节点
        return true;
    }
    return false;
}

//tryReleaseShared在CountDownLatch中的实现
protected boolean tryReleaseShared(int releases) {
    // Decrement count; signal when transition to zero
    for (;;) {
        int c = getState();
        if (c == 0)
            return false;
        int nextc = c-1;
        if (compareAndSetState(c, nextc))
            return nextc == 0;
    }
}

说明:如果释放资源后state==0,说明已经到达latch,此时就可以调用doReleaseShared唤醒等待的线程。

小结

相对其他同步类来说,CountDownLatch可以说是最简单的同步类实现了。它完全依赖了AQS,只要理解了AQS,那么理解它就不成问题了。

作者:泰迪的bagwell
链接:https://www.jianshu.com/p/8eda056df7e2
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    原文作者:JUC
    原文地址: https://blog.csdn.net/yongchao940/article/details/83026608
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞