JUC---CountDownLatch

边学习,边记录,每天进步一点点。

1. CountDownLatch理解
CountDownLatch的本质也是一个"共享锁",允许其他线程完成操作之前,一个或多个线程一直等待。

CountDownLatch在多线程并发编程中充当一个计时器的功能,并且维护一个count的变量,并且其操作都是原子操作,该类主要通过countDown()和await()两个方法实现功能的,首先通过建立CountDownLatch对象,并且传入参数即为count初始值。

如果一个线程调用了await()方法,那么这个线程便进入阻塞状态,并进入阻塞队列。如果一个线程调用了countDown()方法,则会使count-1;当count的值为0时,这时候阻塞队列中调用await()方法的线程便会逐个被唤醒,从而进入后续的操作。

2. 常用方法介绍
(1)CountDownLatch(int count)
传递一个Int值初始化构造器,
在这里插入图片描述
该方法创建一个Sync对象,Sync是CountDownLatch类中的一个私有静态内部类,且继承于AQS。
在这里插入图片描述
Sync的构造方法调用了AQS的setState方法;
在这里插入图片描述
在这里插入图片描述
State在AQS中的定义使用了volatile;
对于CountDownLatch而言,state表示锁计数器。

我们可以看下CountDownLatch中的getCount()方法实现方式
在这里插入图片描述
Sync的getCount()方法实现
在这里插入图片描述
在这里插入图片描述
我们看到,getCount()最终调用了AQS的getState()方法来获取state值,返回的是锁计数器。

(2)await()
在这里插入图片描述
await方法内部是调用AQS的acquireSharedInterruptibly(1)来实现的;
AQS中的acquireSharedInterruptibly()的源码如下:
在这里插入图片描述
如果当前线程是中断状态,则抛出异常InterruptedException。否则,调用tryAcquireShared(arg)尝试获取共享锁;尝试成功则返回,否则就调用doAcquireSharedInterruptibly()。doAcquireSharedInterruptibly()会使当前线程一直等待,直到当前线程获取到共享锁(或被中断)才返回。

我们可以看下tryAcquireShared方法
在这里插入图片描述
我们发现AQS中的方法直接抛出异常,这是由于多态的存在,子类一定有重写的方法,我们需要找下子类的方法。
在这里插入图片描述
tryAcquireShared()的作用是尝试获取共享锁。
如果"锁计数器=0",即锁是可获取状态,则返回1;否则,锁是不可获取状态,则返回-1。

(3)countDown()
在这里插入图片描述
该函数实际上调用releaseShared(1)释放共享锁。
在这里插入图片描述
releaseShared()的目的是让当前线程释放它所持有的共享锁。
它首先会通过tryReleaseShared()去尝试释放共享锁。尝试成功,则直接返回;尝试失败,则通过doReleaseShared()去释放共享锁。
在这里插入图片描述
tryReleaseShared()的作用是释放共享锁,将“锁计数器”的值设置为-1。

3. 总结
(1)CountDownLatch(int count)
初始化需等待执行完成的线程数量;

(2)await()
当前线程进入阻塞状态;当count为0时,唤醒阻塞线程。

(3)countDown()
一个线程执行完毕,调用该方法将count减1;

4. 适用场景
(1)某一线程在开始运行前等待n个线程执行完毕。
比如先写完,才允许读。
(2)实现多个线程开始执行任务的最大并行性。
并行是指多线程同时执行;
并发是指多线程交替执行;
这种场景下,需将count初始化为1,当其变为0时,处于阻塞状态的多个线程将被同时唤醒;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值