JUC的CountDownLatch如何实现

发布时间:2021-12-21 10:22:38 作者:iii
来源:亿速云 阅读:180

这篇文章主要介绍“JUC的CountDownLatch如何实现”,在日常操作中,相信很多人在JUC的CountDownLatch如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JUC的CountDownLatch如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

CountDownLatch 是一个同步辅助工具,用于阻塞当前一个或多个线程以等待其它线程中的操作完成。在构造 CountDownLatch 对象时,我们需要指定一个非负的 count 值,一般情况下,调用 CountDownLatch#await 方法的线程需要阻塞等待该 count 值变为 0 时才能够继续往下执行。

CountDownLatch 实现内幕

CountDownLatch 在实现上同样依赖于 AQS 组件,在 CountDownLatch 的内部定义了一个 Sync 内部类,该类继承自 AbstractQueuedSynchronizer,并复用 AQS 的 state 字段以记录 count 值的变化。CountDownLatch 的核心方法均委托 Sync 进行处理,实现如下:

public class CountDownLatch {

    private final Sync sync;

    public CountDownLatch(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count < 0");
        }
        this.sync = new Sync(count);
    }

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

    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

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

    public long getCount() {
        return sync.getCount();
    }

}

下面我们主要分析一下 CountDownLatch#awaitCountDownLatch#countDown 方法的实现。

首先来看一下 CountDownLatch#await 方法,该方法用于阻塞当前线程,直到 count 值变为 0,或者被其它线程中断。具体实现上,CountDownLatch 直接将请求委托给 AQS 的 AbstractQueuedSynchronizer#acquireSharedInterruptibly 方法进行处理,所以我们下面主要来看一下 CountDownLatch 针对模板方法 AbstractQueuedSynchronizer#tryAcquireShared 的实现,如下:

protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}

实现上非常简单,获取并判定状态值是否为 0,如果是则说明当前线程获取资源成功,能够继续往下执行,否则说明当前线程获取资源失败,需要被添加到同步队列阻塞等待。CountDownLatch 还为 CountDownLatch#await 方法定义了超时版本 CountDownLatch#await(long, TimeUnit)

继续来看一下 CountDownLatch#countDown 方法,该方法用于将 count 值减 1,如果发现 count 值变为 0,则唤醒阻塞等待的线程。具体实现上,CountDownLatch 同样直接将请求委托给 AQS 的 AbstractQueuedSynchronizer#releaseShared 方法进行处理,所以我们下面主要来看一下 CountDownLatch 针对模板方法 AbstractQueuedSynchronizer#tryReleaseShared 的实现,如下:

protected boolean tryReleaseShared(int releases) {
    // Decrement count; signal when transition to zero
    for (; ; ) {
        // 获取 state 状态值
        int c = getState();
        // 如果已经为 0 则说明没有资源可以释放,直接返回 false,避免 state 变为负值
        if (c == 0) {
            return false;
        }
        // 资源数减 1
        int nextc = c - 1;
        if (compareAndSetState(c, nextc)) {
            // 如果为 0,则说明资源全部释放完毕,此时需要唤醒等待的线程
            return nextc == 0;
        }
    }
}

具体实现如代码注释,比较简单。需要注意的一点就是上面步骤中的判 0 操作,刚开始看的时候可能觉得有点多余,但是这一步的主要作用在于保证 state 值不会变为负值。当前 count 值变为 0 时,上述方法会返回 true,接下去 AQS 会执行唤醒之前因为 count 值不为 0 而被打入同步队列的线程。

到此,关于“JUC的CountDownLatch如何实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

推荐阅读:
  1. CountDownLatch的实现原理是什么
  2. JUC的ConcurrentLinkedQueue如何使用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

juc countdownlatch

上一篇:JUC的CyclicBarrier怎么实现

下一篇:网络数据嗅探工具HexInject有什么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》