您的位置 首页 java

深入分析Java并发工具类CountDownLatch

1.什么是CountDownLatch

顾名思义,CountDownLatch是一个倒计时器。

适用于 多线程 中,一个线程需要等待其他线程到达指定状态后再继续执行。

举个场景例子,火箭发射。需要3个步骤

1.设定倒计时的时间

2.等待倒计时完成

3.发射

我们用代码来实现一下这个功能

执行结果

2.CountDownLatch的使用方法

就如同举的场景示例一样,CountDownLatch的使用方式也是分3个步骤

1. 实例化 一个CountDownLatch,并且设置计数

2.进行倒计时的线程,在到达指定状态的时候,调用实例的countdown方法,进行倒计数

3.需要等待的线程调用CountDownLatch实例的await方法,当计数归0时继续执行后续动作

3.源码分析

同样是按照步骤来看

1. 构造函数

如上图所示,CountDownLatch中有个内部类Sync继承了aqs。CountDownLatch只有一个带count的构造函数,这个count是用于初始化aqs的state,且该state是violate的(关于violate可以参考这篇文章 ),因此可以保证多线程环境下的可见。

2.await方法

await是最核心也是最重的方法。

可以看到await方法是调用的sync的acquireSharedInterruptibly,即支持线程中断式地获取共享锁资源

acquireSharedInterruptibly分为两个主要步骤

1.1尝试获取共享资源,即初始化时设置的state是否已经倒计时到0

1.2获取共享资源失败后执行支持线程中断的获取共享锁资源

我们可以这样简单的理解,await方法的本质就是查看state是否归0,归0就直接结束。如果不归0就继续等到state归0,如果知道state归0呢,那就是死循环查询加主动等待的搭配操作。

state尚未归零则执行支持线程中断的获取共享锁资源,正如上面所说死循环查询加主动等待的搭配操作。和aqs的思想一样

2.1插入一个共享模式的节点到队尾

2.2开启死循环查询。因为只有前继前节点是头结点才可以尝试获取共享资源

2.3如果前继前节点是头结点,并且获取到state已经归0。则将该节点设置为头结点,并且传播到后继节点,即如果后继节点是共享模式,且waitStatus正常,则唤醒该节点的线程。

waitStauts主要有以下几个值

CANCELLED=1 线程已经被取消

SIGNAL=-1 后续线程需要被唤醒

CINDITION=-2 线程在等待某个条件

PROPAGATE=-3 下一个AcquireShared应无条件传播

2.4如果前继前节点不是头结点或者state计数尚未归零则park当前线程

3.1查询是否可以park当前线程,前继节点需要为SIGNAL

3.2park当前线程,并且返回线程状态是否被打断

3.countdown方法

countdown方法就很好猜了

1.递减state

2.当state归零的时候唤醒node队列中的状态为SIGNAL(SIGNAL是在判断是否需要park的时候设置的)的线程

文章来源:智云一二三科技

文章标题:深入分析Java并发工具类CountDownLatch

文章地址:https://www.zhihuclub.com/185798.shtml

关于作者: 智云科技

热门文章

网站地图