CountDownLatch 源码解析

阅读须知

  • JDK版本:1.8
  • 文章中使用/* */注释的方法会做深入分析

正文

CountDownLatch 又称为闭锁,基于 AQS 实现,不熟悉 AQS 的同学可以查阅笔者关于 AQS 源码分析的文章进行学习。关于 CountDownLatch 的使用我们就不过多赘述了,直接进入源码分析,我们首先来看一下 CountDownLatch 的构造方法:
CountDownLatch:

public CountDownLatch(int count) {
    // count 参数的含义为:在线程可以通过 await 之前必须调用 countDown 的次数,不能小于0
    if (count < 0) throw new IllegalArgumentException("count < 0");
    /* 构建同步器 */
    this.sync = new Sync(count);
}

CountDownLatch.Sync:

Sync(int count) {
    setState(count);
}

看到这里,我们应该大致猜到了 CountDownLatch 的实现原理,通过递减 AQS 的 state 值来实现闭锁的控制。我们来验证我们的猜想,首先来看 await 方法的实现:
CountDownLatch:

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

await方法的实现很熟悉,我们在 AQS(AbstractQueuedSynchronizer)源码解析(共享锁)这篇文章中已经详细分析过 acquireSharedInterruptibly 方法,是可以响应中断的共享锁获取方法,方法中会调用由子类实现的 tryAcquireShared 方法实现共享锁获取逻辑,我们来看 CountDownLatch 对于 tryAcquireShared 方法的实现:
CountDownLatch.Sync:

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

我们分析过 tryAcquireShared 方法的返回值,这里当 AQS 的 state 为0时返回1,代表获取锁成功,不为0(大于0)时返回-1代表获取锁失败,要进行阻塞等待。按照我们的猜想,countDown 方法应该是递减 AQS 的 state 变量的值直到为0,然后唤醒调用 await 方法阻塞的线程。我们来看一下 countDown 方法的实现:
CountDownLatch:

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

这里的 releaseShared 释放共享锁方法同样来自于 AQS,方法中首先会调用由子类覆盖的 tryReleaseShared 方法,通过尝试设置 state 变量来释放共享锁,我们来看 CountDownLatch 对于 tryReleaseShared 方法的实现:
CountDownLatch.Sync:

protected boolean tryReleaseShared(int releases) {
    // 递减 state,值为0值发出唤醒信号
    for (;;) {
        int c = getState();
        // 如果 state 的值已经为0,说明已经有另外一个线程发出了唤醒信号,这里返回 false 无需再次进行唤醒操作
        if (c == 0)
            return false;
        // 递减 state
        int nextc = c-1;
        // CAS 设置 state 的值
        if (compareAndSetState(c, nextc))
            // 如果 state 的值为0,则返回true进行共享锁的释放操作
            return nextc == 0;
    }
}

由此可见,我们的猜想是正确的。整体来看,CountDownLatch 就是基于 AQS 的共享锁实现,如果理解了 AQS 的共享锁,理解 CountDownLatch 的实现原理还是比较简单的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值