Java多线程并发控制工具CountDownLatch,实现原理及案例

Wesley13
• 阅读 744

闭锁(CountDownLatch)是Java多线程并发中的一种同步器,它是JDK内置的同步器。通过它可以定义一个倒计数器,当倒计数器的值大于0时,所有调用await方法的线程都会等待。而调用countDown方法则可以让倒计数器的值减一,当倒计数器值为0时所有等待的线程都将继续往下执行。

闭锁的主要应用场景是让某个或某些线程在某个运行节点上等待N个条件都满足后才让所有线程继续往下执行,其中倒计数器的值为N,每满足一个条件倒计数器就减一。比如下图中,倒计数器初始值为3,然后三个线程调用await方法后都在等待。随后倒计数器减一为2,再减一为1,最后减一为0,所有等待的线程都往下继续执行。

Java多线程并发控制工具CountDownLatch,实现原理及案例

01

三要素

闭锁的三要素为:倒计数器的初始值、await方法以及countdown方法。倒计数器的初始值在构建CountDownLatch对象时指定,它表示我们需要等待的条件个数。await方法能让线程进入等待状态,等待的条件是倒计数器的值大于0。countdown方法用于将倒计数器的值减一。

02

实现原理

先前介绍过如何基于AQS同步器实现一个自定义同步器,实际上CountdownLatch也是基于AQS来实现的,只要使用AQS的共享模式即可以轻松实现闭锁。

Java多线程并发控制工具CountDownLatch,实现原理及案例 下面我们看详细的实现代码,CountdownLatch类的构造函数需要传入一个整型参数,表示倒计数器的初始值,对应着AQS的state状态变量。按照官方推荐的自定义同步器的做法,将继承了AQS类的子类Sync作为CountdownLatch类的内部类,而CountdownLatch同步器中相关的操作只需代理成子类中对应的方法即可。比如await方法和countDown方法分别调用Sync子类的acquireSharedInterruptibly方法和releaseShared方法。

Sync子类中需要我们实现的两个方法是tryAcquireShared和tryReleaseShared,分别用于获取共享锁和释放共享锁。先看获取共享锁的逻辑,如果状态变量等于0则返回1,当倒计数器的值减少到0的时候全部线程都可以直接尝试得到共享锁,而当倒计数器的值为非0时使之返回-1交给AQS进行入队管理。然后看释放共享锁的逻辑,主要是通过自旋来进行减一操作,getState方法获取状态变量,将其值减一后使用compareAndSetState方法进行CAS修改状态值。

Java多线程并发控制工具CountDownLatch,实现原理及案例

03

案例 1

第 一个例子是创建一个CountdownLatch对象作为倒计数器,其值为2。 然后线程一调用await方法进行等待,线程二调用countDown方法将倒计数器的值减一并往下执行。 线程三再调用countDown方法将倒计数器的值再减一并往下执行,此时倒计数器的值为0,线程一停止等待并往下执行。

Java多线程并发控制工具CountDownLatch,实现原理及案例

下面的例子输出如下,thread1调用await方法后进入等待状态,thread2睡眠两秒后调用countDown方法并往下执行,thread3睡眠四秒后调用countDown方法并往下执行,最后thread1才停止等待继续往下执行。

Java多线程并发控制工具CountDownLatch,实现原理及案例

Java多线程并发控制工具CountDownLatch,实现原理及案例

04

 案例 2

第二个例子是创建一个CountdownLatch对象作为倒计数器,其值为2。 然后线程一和线程二都分别调用await方法进行等待,线程三则调用两次countDown方法将倒计数器的值减二并往下执行,此时倒计数器的值为0,线程一和线程二停止等待并往下执行。

Java多线程并发控制工具CountDownLatch,实现原理及案例

下面的例子输出如下,thread1和thread2调用await方法后进入等待状态,然后主线程调用countDown方法后休眠两秒钟。此时的倒计数器值为1,所以thread1和thread2继续等待,直到主线程休眠结束后再次调用countDown方法后,thread1和thread2才能继续往下执行。

Java多线程并发控制工具CountDownLatch,实现原理及案例

Java多线程并发控制工具CountDownLatch,实现原理及案例

05

 总结

CountDownLatch中文名为闭锁,是JDK内置的一个同步器,它通过倒计数器的值来控制多线程并发。它主要由倒计数器的初始值、await操作和countdown操作。内部的实现是基于AQS同步器,并且我们提供了两个例子让大家了解闭锁的使用场景和使用方法。

- END -

Java多线程并发控制工具CountDownLatch,实现原理及案例

本文分享自微信公众号 - 码农架构(iByteCoding)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java并发编程之二
CountDownLatch类  允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。  CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成了任务,然后在
Wesley13 Wesley13
3年前
java并发中CountDownLatch的使用
java并发中CountDownLatch的使用在java并发中,控制共享变量的访问非常重要,有时候我们也想控制并发线程的执行顺序,比如:等待所有线程都执行完毕之后再执行另外的线程,或者等所有线程都准备好了才开始所有线程的执行等。这个时候我们就可以使用到CountDownLatch。简单点讲,CountDownLatch存有一个放在QueuedS
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
3年前
Java多线程并发控制工具信号量Semaphore,实现原理及案例
信号量(Semaphore)是Java多线程兵法中的一种JDK内置同步器,通过它可以实现多线程对公共资源的并发访问控制。一个线程在进入公共资源时需要先获取一个许可,如果获取不到许可则要等待其它线程释放许可,每个线程在离开公共资源时都会释放许可。其实可以将Semaphore看成一个计数器,当计数器的值小于许可最大值时,所有调用acquire方法的线程都可以得到
Stella981 Stella981
3年前
CountDownLatch和CylicBarrier以及Semaphare你使用过吗
CountDownLatch是什么CountDownLatch的字面意思:倒计时门栓它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒。它通过调用await方法让线程进入阻塞状态等待倒计时0时唤醒。它通过线程调用countDown方法让倒计时中的计数器减去1,当计数器为0时,会唤醒哪些因为调用了await而阻塞的线程。
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这