CountDownLatch认知——同步协调器

原创 2016年08月29日 09:55:48

简介

java.util.concurrent.CountDownLatchJDK1.5引入的并法包中的一个工具类,用来做并发线程间的同步。

我们来看一下它的类说明信息:

一个同步辅助,它允许一个或者多个线程等待——直到一系列在其他线程中的操作完成之后才进行。

一个CountDownLatch 由一个给定的count总数初始化。await方法会一直阻塞直到当前count值被countDown方法的调用减为零,之后,所有等待线程被释放,任何后续await方法的调用立即返回。这种现象是一次性的——count值不能被重置。如果你想要count能被重置,请考虑使用CyclicBarrier

一个CountDownLatch是一个万能的同步工具,它可以被用在很多场景中。CountDownLatch类似于简单开关门闩,或者说大门:所有调用await的线程在大门外等待直到大门被一个调用countDown的线程打开。一个CountDownLatch的计数器被初始化为N,可以使一个线程等待直到N个线程完成了某些操作,或者某些操作被完成了N次。

CountDownLatch 一个有用的特性是它并不要求调用countDown的线程必须等待count值减为零之后才能进行,它只是简单地阻止任意的线程执行传递await信号直到所有线程可以传递这个信号。


协调器

所以,我所理解的这个类的最主要的作用就是:用来做线程同步的协调器
讲一个我理解的场景:

大学里的体育课,这里边有两个角色:体育老师和学生。上课开始的前15分钟,体育老师定为热身阶段,让大家先去跑个1000米,跑完的同学先去自由休息,听老师命令,到指定地点正式上课。

这个场景就非常适合用CountDownLath来做协调。
伪代码标识为:

//体育老师宣布活动
//以学生总数目作为CountDownLath的计数器的初始值
//每个学生都是一个线程,并持有CountDownLath的引用
//所有学生在起跑线预备,等待体育老师鸣哨
//体育老师鸣哨,计时开始,然后就去凉快的地方待着
//学生在听到哨声之后,开始各自奔跑
//每个学生在跑过终点之后,CountDownLath的计数器减一
//所有跑完,CountDownLath为零,老师回到操场,宣布下一个活动

示例

官方给的使用样例:这里有一对儿类,它们有一组工作线程使用两个countdown latch。

一开始的start(开始)信号,阻止任意的worker执行直到driver已经准备好执行;
第二个的completion(完成)信号,允许dirver等待直到所有worker已经完成。

 class Driver { // ...
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i) // create and start threads
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // don't let run yet
     startSignal.countDown();      // let all threads proceed
     doSomethingElse();
     doneSignal.await();           // wait for all to finish
   }
 }
 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
     this.startSignal = startSignal;
     this.doneSignal = doneSignal;
   }
   public void run() {
     try {
       startSignal.await();
       doWork();
       doneSignal.countDown();
     } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }}

另外一个典型的应用是把一个问题分解为N个部分,每个部分用一个Runnable来描述,一个Runnable执行每个部分并削减latch,然后将所有的Runnable送到一个Executor的队列中。当所有的子部分都完成了,协调线程会传递一个await信号(当线程必须以这种方式重复削减的时候,请使用CyclicBarrier)。

 class Driver2 { // ...
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i < N; ++i) // create and start threads
       e.execute(new WorkerRunnable(doneSignal, i));

     doneSignal.await();           // wait for all to finish
   }
 }
 class WorkerRunnable implements Runnable {
   private final CountDownLatch doneSignal;
   private final int i;
   WorkerRunnable(CountDownLatch doneSignal, int i) {
     this.doneSignal = doneSignal;
     this.i = i;
   }
   public void run() {
     try {
       doWork(i);
       doneSignal.countDown();
     } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }

内存一致性影响:直到计数器减为零,线程中countDown方法被调用之前的动作happen-before于后续的另外一个线程中相应的await()方法成功返回之后的动作。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android引导页——可跟踪定位的引导页协调器

需求由于项目需要实现指导新用户使用App功能的引导页。效果图(这是实现后的截图了) 分析与解决 显示引导页 方案:只要inflate相应的layout,并添加到decorView里面。 指示的Vi...

协调器的组网,终端设备和路由设备发现网络以及加入网络 设备绑定、两节点间串口通信

 第一个功能:协调器的组网,终端设备和路由设备发现网络以及加入网络 //第一步:Z-Stack  由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始...

错误信息:Microsoft 分布式事务处理协调器(MS DTC)已取消此分布式事务

在联机文档中是这样描述MS DTC的: Microsoft 分布式事务处理协调器 (MS DTC) 是一个事务管理器,它允许客户端应用程序在一个事务中包含多个不同的数据源。MS DTC 协调在所有已...

【转】协调器启动网络(一)

Zigbee标准中规定只有协调器在未加入其它网络时才能发起PAN网络,某个节点在要调用网络发起函数之前,要对这个节点是否已经加入网络和节点类型进行判断。     if( ! nib->joi...

门禁协调器

  • 2015年05月16日 00:20
  • 20.48MB
  • 下载

基于嵌入式ARM-Linux无线ZigBee协调器驱动设计

来源:电子技术应用   2013-8-22 17:06:12 【提要】本文通过上位机处理器ARM9CS...

已知网络地址在协调器中查询MAC地址

出自 已知网络地址查询MAC地址 1、实验内容: 协调器上电后建立网路,路由器自动加入网络。然后路由器调用调用相关的API函数获得某一网络号节点的MAC地址,然后通过串口将其发送到PC端的串口调试...
  • PZ0605
  • PZ0605
  • 2017年04月04日 09:13
  • 312

IAR中路由器、协调器、终端的配置区别

路由器 终端" title="[原创]详解在程序中怎样区分协调器 路由器 终端" style="margin:0px; padding:0px; border:0px; list-style:none...

zigbee网络启动流程 ---- 协调器

main()->osal_init_system()->osalInitTasks()->ZDApp_Init() 进入ZDApp_Init()函数: void ZDApp_Init( uin...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CountDownLatch认知——同步协调器
举报原因:
原因补充:

(最多只允许输入30个字)