概述

  CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。

  CountDownLatch使用一个计数器count实现,构建CountDownLatch时需要使用给定的count初始化CountDownLatch。在count到达0之前,调用await()方法的线程将一直阻塞,当count到达0时,会唤醒所有阻塞的线程。注意:计数器count无法被重置,即只能实现一次这种功能,这也是CountDownLatch与CyclicBarrier的区别。

  内存一致性效果:线程中调用 countDown() 之前的操作 happen-before 紧跟在从另一个线程中对应 await() 成功返回的操作。

使用

  CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。

  提供的方法:

1 //使当前线程阻塞直到计数器count变为0,除非被中断
2 public void await() throws InterruptedException
3 //使当前线程阻塞直到计数器count变为0,除非被中断或超过了指定时间
4 public boolean await(long timeout, TimeUnit unit) throws InterruptedException
5 //将计数器count递减,若count变为0则唤醒所有等待的线程
6 public void countDown()
7 //返回计数器count值
8 public long getCount()

  使用示例:Driver主线程中控制N个Worker线程的启动,并等待所有Worker线程完成再退出。

 1 class Driver { // ...
 2     void main() throws InterruptedException {
 3         CountDownLatch startSignal = new CountDownLatch(1);    //启动信号
 4         CountDownLatch doneSignal = new CountDownLatch(N);    //完成信号
 5
 6         for (int i = 0; i < N; ++i) // create and start threads
 7             new Thread(new Worker(startSignal, doneSignal)).start();
 8
 9         doSomethingElse();            // don't let run yet
10         //将启动信号的计数器置为0,启动等待的Worker线程
11         startSignal.countDown();      // let all threads proceed
12         doSomethingElse();
13         //等待N个Worker线程完成
14         doneSignal.await();           // wait for all to finish
15     }
16 }
17
18 class Worker implements Runnable {
19     private final CountDownLatch startSignal;
20     private final CountDownLatch doneSignal;
21     Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
22         this.startSignal = startSignal;
23         this.doneSignal = doneSignal;
24     }
25     public void run() {
26         try {
27             startSignal.await();    //等待启动信号
28             doWork();
29             doneSignal.countDown();    //发出完成信号,将完成信号的计数器减1
30         } catch (InterruptedException ex) {} // return;
31     }
32
33     void doWork() { ... }
34 }

实现原理

  CountDownLatch基于AQS实现,使用AQS的同步状态state表示计数器count。

  先看一下CountDownLatch的内部类Syns的实现:

 1 private static final class Sync extends AbstractQueuedSynchronizer {
 2     private static final long serialVersionUID = 4982264981922014374L;
 3
 4     Sync(int count) {
 5         setState(count);    //设置同步状态state为count
 6     }
 7
 8     int getCount() {
 9         return getState();    //查询同步状态
10     }
11     //重写AQS的共享式获取同步状态的方法。当state=0时返回1,获取成功;当state=1时返回-1,获取失败。
12     protected int tryAcquireShared(int acquires) {
13         return (getState() == 0) ? 1 : -1;
14     }
15     //重写AQS的共享式释放同步状态的方法。基于自旋CAS递减同步状态
16     protected boolean tryReleaseShared(int releases) {
17         // Decrement count; signal when transition to zero
18         //如果state=0,那么直接返回false
19         //如果state>0,那么递减state。若更新后的state=0则返回true,释放同步状态成功;反之,返回false。
20         for (;;) {
21             int c = getState();
22             if (c == 0)
23                 return false;
24             int nextc = c-1;
25             if (compareAndSetState(c, nextc))
26                 return nextc == 0;
27         }
28     }
29 }

    由Sync源码可以看出,CountDownLatch基于AQS的共享式获取和释放同步状态的机制实现。

  await()

1 //调用AQS提供的共享式可中断获取同步状态方法。
2 //若获取成功(state=0),继续执行后续代码;否则(state>0),阻塞当前线程。
3 public void await() throws InterruptedException {
4     sync.acquireSharedInterruptibly(1);
5 }

  countDown()

1 //调用AQS提供的共享式释放同步状态方法。
2 //若释放成功(tryReleaseShared返回true),唤醒同步队列上的后继节点;若释放失败(tryReleaseShared返回false),不做任何操作。
3 public void countDown() {
4     sync.releaseShared(1);
5 }

转载于:https://www.cnblogs.com/zaizhoumo/p/7786893.html

Java并发编程--CountDownLatch相关推荐

  1. Java 并发编程CountDownLatch的应用与源码解析

    应用场景 CountDownLatch是一个多线程控制工具.用来控制线程的等待. 设置需要countDown的数量,然后每一个线程执行完毕后调用countDown()方法,而在主线程中调用await( ...

  2. Java并发编程-CountDownLatch

    2019独角兽企业重金招聘Python工程师标准>>> 1. 应用场景 CountDownLatch是并发包中用来控制一个或者多个线程等待其他线程完成操作的并发工具类.现以工作中的一 ...

  3. java 并发统计_java并发编程|CountDownLatch计数器

    0x01,CountDownLatch介绍 CountDownLatch是一个计数器,作为java并发编程中三个组件之一,这个组件的使用频率还是很多的.这里分享下自己画的java并发编程组件的图,后面 ...

  4. 【Java 并发编程】CountDownLatch 简介

    文章目录 I CountDownLatch 概念 II CountDownLatch 使用流程 III CountDownLatch API 简介 I CountDownLatch 概念 1. 概念 ...

  5. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    2019独角兽企业重金招聘Python工程师标准>>> Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一 ...

  6. Java 并发编程系列之闭锁(CountDownLatch)

    在讲闭锁之前,我们先来思考一个问题:在多线程环境下,主线程打印一句话,如何保证这句话最后(其他线程全部执行完毕)打印? 博主目前可以想到的实现方式有两种.一种是通过 join() 方法实现,另一种就是 ...

  7. Java并发编程工具类:CountDownLatch、CyclicBarrier、Semaphore

    在jdk5中,java提供了一些非常有用的辅助工具类,包括CountDownLatch和CyclicBarrier(两者都可以实现线程之间的通信).Semaphore(控制方法被线程访问的数量),他们 ...

  8. 【Java并发编程实战】 5.5.1章节 闭锁 CountDownLatch 实现

    文章目录 1. 什么是闭锁 2. 闭锁的应用场景 3. 闭锁的实现 4. CountDownLatch原理 5. 使用案例 5.1 入门案例 5.2 复杂案例 1. 什么是闭锁 闭锁(latch)是一 ...

  9. Java并发编程笔记之 CountDownLatch闭锁的源码分析

    转 自: Java并发编程笔记之 CountDownLatch闭锁的源码分析 ​ JUC 中倒数计数器 CountDownLatch 的使用与原理分析,当需要等待多个线程执行完毕后在做一件事情时候 C ...

最新文章

  1. Windows配置Oracle Instant Client
  2. 简析 Google Gadget 的数据丢失原因
  3. 关于android设备管理器的一些分析
  4. 数学 —— 巧用进制
  5. python中的元类_Python中的元类(metaclass)
  6. [洛谷 P3992] [BJOI2017]开车
  7. Docker笔记4 端口映射和容器互联
  8. 处理Excel电子表格
  9. 网络编辑的内容制作及管理规范
  10. 学习笔记 Logistic阻滞人口预测模型
  11. 基于FPGA的交通灯设计
  12. IDEA社区版下载与安装详细教程
  13. iOS平台游戏安全之IPA破解原理及防御(第三弹)
  14. 豆瓣电影Top250信息爬取并保存到excel文件中!
  15. Abaqus2019的abaqus_v6.env在哪里
  16. 1周岁的宝宝营养食谱(3)
  17. 语义分割代码实现流程
  18. 5注册激活_国家医保服务平台APP激活绑定流程
  19. 【机器学习实战】KNN
  20. Java入门 - 分支结构

热门文章

  1. 关于Docker COPY指令只能使用相对路径的说明
  2. Spring Boot 2.3.x 分层构建 Docker 镜像实战
  3. scala函数定义示例
  4. maven快照版本机制详解
  5. Scala使用半生对象来创建伴生类对象(默认单例)
  6. Apollo后台配置:添加部门
  7. Python3序列解包
  8. Hystrix熔断器机制
  9. RocketMQ简介及核心概念说明
  10. latex在algorithm环境或表格中插入圆圈脚注