type
status
date
slug
summary
tags
category
icon
password
原文
CountDownLatch 是 Java 并发包(
java.util.concurrent JUC)中基于 AQS(AbstractQueuedSynchronizer) 实现的同步工具类,核心功能是让一个或多个线程等待其他线程完成指定操作后再继续执行。它通过 “计数” 机制控制线程同步:初始化时设定一个计数,线程完成操作后调用 countDown() 减少计数,等待线程调用 await() 阻塞直到计数归 0。
核心方法
- public CountDownLatch(int count) 构造器
- countDown()
计数减 1:若减后计数 = 0,唤醒所有等待线程;若已为 0,调用无效。
- await()
等待计数归 0:若当前计数 > 0,当前线程阻塞;若计数 = 0,直接返回;支持响应中断(被中断时抛异常)。
工作流程

CountDownLatch为所有工作线程共享。
CountDownLatch内部维护了一个计数器,例如图1有3 个工作线程,那么计数器则为 3。
等待线程调用 CountDownLatch对象的 await 方法,加入到CountDownLatch对象内部的队列中,此时线程会进入阻塞状态(WAITING)。
工作线程在完成业务逻辑时,调用countDown方法,CountDownLatch对象会 CAS 操作state 递减操作。如果计数器为0,则会依次唤醒队列中的等待线程。
源码解析
构造器
首先创建一个 CountDownLatch 对象,构造参数为计数器,对应工作的线程数。该计数器必须≥0。
CountDownLatch 静态内部类Sync 继承了
AbstractQueuedSynchronizer ,构造器count 参数直接指定 Sync state 属性,该属性其实就是一个计数器。countDown
countDown 方法实际调用的是 AQS 同步的基础方法。
countDown 方法应该在 finally 块中执行。
- 即使工作线程发生了异常中断,也能保证 CountDownLatch 的计数器能够减1。
- 如果不是在finally块执行,工作线程发生中断或其他异常,计数器不能正确递减至归 0,则等待线程则会一直处于阻塞状态。
具体逻辑包括两部分:计数器递减、唤醒等待线程
- 计数器递减
每个工作线程调用一次 countDown 方法是对 CountDownLatch对象中的 Sync维护的计数器(state)进行递减(减 1)操作。
- 计数器为 0,则唤醒队列中的等待线程
计数器为 0 即所有工作线程都已完成了任务。
从头节点开始遍历,依次唤醒队列中的等待线程。
await
await 是由等待线程来调用的,即等待工作线程完成的线程。
可以由多个线程来调用,调用该方法后进入阻塞状态或者说挂起状态。
这一部分功能都是借助 AQS 公共方法来实现的。
tryAcquireShared
- state等于0 ,返回1,表示工作线程都已完成工作。
如果一开始创建CountDownLatch对象时就是为 0,则等待线程也无法进入到阻塞状态。
- state不等于 0,则表示还有工作线程的工作未完成。
doAcquireSharedInterruptibly
计数器不为0时,等待线程加入队列。
加入队列后等待线程进入阻塞状态。
(1) 处理队列初始化,以及等待线程入列操作。
(2) 处理当前Node节点(当前线程构成的Node 节点)的 waitStatus
设置前驱节点的 waitStatus为 -1。
(3) 等待线程如果调用了 interrupt方法,那么在队列中需要将等待线程的节点清除或设置等待节点标记为已取消。
- Author:newrain-zh
- URL:https://alex.sh.cn/article/CountDownLatch
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!


