一文彻底弄懂JUC工具包的CountDownLatch的设计理念与底层原理

CountDownLatch 是 Java 并发包(java.util.concurrent)中的一个同步辅助类,它允许一个或多个线程等待一组操作完成。

一、设计理念

CountDownLatch 是基于 AQS(AbstractQueuedSynchronizer)实现的。其核心思想是维护一个倒计数,每次倒计数减少到零时,等待的线程才会继续执行。它的主要设计目标是允许多个线程协调完成一组任务。

1. 构造函数与计数器
public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);
}

构造 CountDownLatch 时传入的 count 决定了计数器的初始值。该计数器控制了线程的释放。

2. AQS 支持的核心操作

AQS 是 CountDownLatch 的基础,通过自定义内部类 Sync 实现,Sync 继承了 AQS 并提供了必要的方法。以下是关键操作:

  • acquireShared(int arg): 如果计数器值为零,表示所有任务已完成,线程将获得许可。
  • releaseShared(int arg): 每次调用 countDown(),会减少计数器,当计数器降到零时,AQS 将释放所有等待的线程。
3. 实现细节
  • countDown():调用 releaseShared() 减少计数器,并通知等待线程。
  • await():调用 acquireSharedInterruptibly(1),如果计数器非零则阻塞等待。

二、底层原理

CountDownLatch 的核心是基于 AbstractQueuedSynchronizer(AQS)来管理计数器状态的。AQS 是 JUC 中许多同步工具的基础,通过一个独占/共享模式的同步队列实现线程的管理和调度。CountDownLatch 采用 AQS 的共享锁机制来控制多个线程等待一个条件。

1. AQS 的共享模式

AQS 设计了两种同步模式:独占模式(exclusive)和共享模式(shared)。CountDownLatch 使用共享模式:

  • 独占模式:每次只能一个线程持有锁,如 ReentrantLock
  • 共享模式:允许多个线程共享锁状态,如 SemaphoreCountDownLatch

CountDownLatchawait()countDown() 方法对应于 AQS 的 acquireShared()releaseShared() 操作。acquireShared() 会检查同步状态(计数器值),若状态为零则立即返回,否则阻塞当前线程,进入等待队列。releaseShared() 用于减少计数器并唤醒所有等待线程。

2. Sync 内部类的设计

CountDownLatch 通过一个私有的内部类 Sync 来实现同步逻辑。Sync 继承自 AQS,并重写 tryAcquireShared(int arg)tryReleaseShared(int arg) 方法。

static final class Sync extends AbstractQueuedSynchronizer {Sync(int count) {setState(count);}protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;}protected boolean tryReleaseShared(int releases) {// 自旋减计数器for (;;) {int c = getState();if (c == 0)return false;int nextc = c - 1;if (compareAndSetState(c, nextc))return nextc == 0;}}
}
  • tryAcquireShared(int):当计数器为零时返回 1(成功获取锁),否则返回 -1(阻塞)。
  • tryReleaseShared(int):每次 countDown() 减少计数器值,当计数器到达零时返回 true,唤醒所有阻塞线程。
3. CAS 操作确保线程安全

tryReleaseShared 方法使用 CAS(compare-and-set)更新计数器,避免了锁的开销。CAS 操作由 CPU 原语(如 cmpxchg 指令)支持,实现了高效的非阻塞操作。这种设计保证了 countDown() 的线程安全性,使得多个线程能够并发地减少计数器。

4. 内部的 ConditionObject

CountDownLatch 不支持复用,因为 AQS 的 ConditionObject 被设计为单一触发模式。计数器一旦降至零,CountDownLatch 无法重置,只能释放所有线程,而不能再次设置初始计数器值。这就是其不可复用的根本原因。

三、应用场景

  1. 等待多线程任务完成CountDownLatch 常用于需要等待一组线程完成其任务后再继续的场景,如批处理任务。
  2. 并行执行再汇总:在某些数据分析或计算密集型任务中,将任务分割成多个子任务并行执行,主线程等待所有子任务完成后再汇总结果。
  3. 多服务依赖协调:当一个服务依赖多个其他服务时,可以使用 CountDownLatch 来同步各个服务的调用,并确保所有依赖服务准备好之后再执行主任务。

四、示例代码

以下示例展示如何使用 CountDownLatch 实现一个并发任务等待所有子任务完成的机制。

import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {private static final int TASK_COUNT = 5;private static CountDownLatch latch = new CountDownLatch(TASK_COUNT);public static void main(String[] args) throws InterruptedException {for (int i = 0; i < TASK_COUNT; i++) {new Thread(new Task(i + 1, latch)).start();}// 主线程等待所有任务完成latch.await();System.out.println("所有任务已完成,继续主线程任务");}static class Task implements Runnable {private final int taskNumber;private final CountDownLatch latch;Task(int taskNumber, CountDownLatch latch) {this.taskNumber = taskNumber;this.latch = latch;}@Overridepublic void run() {try {System.out.println("子任务 " + taskNumber + " 开始执行");Thread.sleep((int) (Math.random() * 1000)); // 模拟任务执行时间System.out.println("子任务 " + taskNumber + " 完成");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {latch.countDown(); // 完成一个任务,计数器减一}}}
}

五、与其他同步工具的对比

1. CyclicBarrier

原理和用途

  • CyclicBarrier 也允许一组线程相互等待,直到所有线程到达屏障位置(barrier point)。
  • 它适合用于多阶段任务分阶段汇聚,如处理分块计算时每阶段汇总结果。

底层实现

  • CyclicBarrier 内部通过 ReentrantLockCondition 实现,屏障次数可以重置,从而支持循环使用。

与 CountDownLatch 的对比

  • CyclicBarrier可复用性使其适合重复的同步场景,而 CountDownLatch 是一次性的。
  • CountDownLatch 更灵活,允许任意线程调用 countDown(),适合分布式任务。CyclicBarrier 需要指定的线程达到屏障。
2. Semaphore

原理和用途

  • Semaphore 主要用于控制资源访问的并发数量,如限制数据库连接池的访问。

底层实现

  • Semaphore 基于 AQS 的共享模式实现,类似于 CountDownLatch,但允许通过指定的“许可证”数量控制资源。

与 CountDownLatch 的对比

  • Semaphore 可以动态增加/减少许可,而 CountDownLatch 只能递减。
  • Semaphore 适合控制访问限制,而 CountDownLatch 用于同步点倒计数。
3. Phaser

原理和用途

  • PhaserCyclicBarrier 的增强版,允许动态调整参与线程的数量。
  • 适合多阶段任务同步,并能随时增加或减少参与线程。

底层实现

  • Phaser 内部包含一个计数器,用于管理当前阶段的参与线程,允许任务动态注册或注销。

与 CountDownLatch 的对比

  • Phaser 更适合复杂场景,能够灵活控制阶段和参与线程;CountDownLatch 的结构简单,只能用于一次性同步。
  • Phaser 的设计更复杂,适合长时间、多线程协调任务,而 CountDownLatch 更适合简单任务等待。
4、总结

CountDownLatch 是一个轻量级、不可复用的倒计数同步器,适合简单的一次性线程协调。其基于 AQS 的共享锁实现使得线程等待和计数器更新具有高效的并发性。虽然 CountDownLatch 不具备重用性,但其设计简洁,尤其适合需要等待多线程任务完成的场景。

与其他 JUC 工具相比:

  • CyclicBarrier 更适合多阶段同步、阶段性汇总任务。
  • Semaphore 适合资源访问控制,具有可控的许可量。
  • Phaser 灵活性更高,适合动态参与线程、复杂多阶段任务。

选择适合的同步工具,取决于任务的性质、线程参与动态性以及是否需要重用同步控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/9492.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

03集合基础

目录 1.集合 Collection Map 常用集合 List 接口及其实现 Set 接口及其实现 Map 接口及其实现 Queue 接口及其实现 Deque 接口及其实现 Stack类 并发集合类 工具类 2.ArrayList 3.LinkedList 单向链表的实现 1. 节点类&#xff08;Node&#xff09; 2. 链表类&a…

6KBhtm+js实现提交名单随机抽取功能适用活动或课堂随机点名

<!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>名单抽奖系统</title> <style> *{ma…

面向对象的需求分析和设计(一)

[toc] 1. 引言 前一篇文章《我对需求分析的理解》提到了面向对象分析和设计&#xff0c;正好最近又重新有重点的读了谭云杰著的《Think in UML》&#xff0c;感觉有必要写把书中一些核心内容观点以及自己的想法整理出来&#xff0c;一是方便自己日后的复习&#xff0c;另外也…

树的存储结构-树,二叉树,森林的相互转换

双亲表示法存储树 优点:查找指定结点的双亲十分方便 缺点:查指定结点的孩子只能从头遍历 插入操作:插入对位无须按照某种顺序 删除操作1:将指定结点的parent数据赋值为-1表示为空(删除节点为叶子节点) 删除操作2:将最后一个数据覆盖到指定结点的数据域(删除节点为叶子节点…

OpenGL学习笔记(四) RGBA颜色

RGBA模式中&#xff0c;每一个像素会保存以下数据&#xff1a;R值&#xff08;红色分量&#xff09;、G值&#xff08;绿色分量&#xff09;、B值&#xff08;蓝色分量&#xff09;和A值&#xff08;alpha分量&#xff09;。其中红、绿、蓝三种颜色相组合&#xff0c;就可以得到…

机器学习2_支持向量机_线性可分——MOOC

目录 定义 线性可分&#xff08;Linear Separable&#xff09; 线性不可分&#xff08;Nonlinear Separable&#xff09; 数学化定义 问题描述 优化问题 线性可分定义 假定训练样本集是线性可分的 1、最小化&#xff08;Minimize&#xff09;&#xff1a; 2、限制条件…

零基础学习Spring AI Java AI使用向量数据库postgresql 检索增强生成 RAG

零基础学习Spring AI Java AI使用向量数据库postgresql 检索增强生成 RAG 向量数据库是一种特殊类型的数据库&#xff0c;在人工智能应用中发挥着至关重要的作用。 在向量数据库中&#xff0c;查询与传统的关系数据库不同。它们不是进行精确匹配&#xff0c;而是执行相似性搜…

口子查好做吗?有什么特点?

大家好&#xff0c;我是橙河老师&#xff0c;一家问卷公司老板&#xff0c;今天讲一讲“口子查好做吗&#xff1f;有什么特点&#xff1f;” 1.口子查是公开性资源&#xff0c;由国外问卷公司直接发布在主流的平台上&#xff0c;比如我们的抖音、百度这些平台&#xff0c;竞争…

开放式耳机性价比排行榜:从入门到高端的全方位推荐

在购买开放式耳机时&#xff0c;性价比是一个重要的考虑因素。开放式耳机性价比排行榜可以为我们提供从入门到高端的全方位推荐。但是&#xff0c;在关注排行榜的同时&#xff0c;我们也不能忽视一些关于开放式耳机的谣言&#xff0c;如对耳朵有伤害、完全不漏音、是否适合所有…

计算机毕业设计Spark+大模型知识图谱中药推荐系统 中药数据分析可视化大屏 中药爬虫 机器学习 中药预测系统 中药情感分析 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

WEB:如何优化大数据菜单展示的攻略指南

1、简述 在前端开发中&#xff0c;树结构菜单是常见的 UI 组件&#xff0c;尤其是在展示层级复杂、数据量庞大的场景下。如何优化大数据量的树结构菜单展示&#xff0c;提高性能和用户体验&#xff0c;是一个值得探讨的话题。本文将介绍一些优化技术和实践&#xff0c;帮助开发…

MySQL表的增删改查(CRUD3约束)

这次我们开始先不复习嗷&#xff0c;等到把数据表的删除说完咱们统一&#xff0c;总结书写 1.数据表的删除&#xff1a; 语法&#xff1a; 1. 使用 DROP TABLE 语句删除单个表 基本语法&#xff1a;DROP TABLE [IF EXISTS] table_name; table_name是要删除的表的名称。IF EXIS…

【每日推荐】使用 Ollama 平台上的 Llama 3.2-vision 模型进行视频目标检测

&#x1f680; 使用 Ollama 平台上的 Llama 3.2-vision 模型进行视频目标检测 在本期推荐的文章中&#xff0c;视频将展示如何通过 Ollama 平台上的 Llama 3.2-vision 多模态模型&#xff0c;结合 Python 和 FastAPI 框架&#xff0c;轻松实现视频目标检测功能。只需要简单的代…

【华为云-云驻共创】UCS跨云多活容灾:让业务高可用不再是难题

【摘要】云原生应用深入到企业各个业务场景&#xff0c;云原生正在走向分布式化&#xff0c;跨云跨域统一协同治理&#xff0c;保证一致应用体验&#xff0c;这些新的需求日益凸显。而容灾是确保服务高可用的保障&#xff0c;但即使应用部署在云上&#xff0c;也无法避免市政方…

ssm080削面快餐店点餐服务系统的设计与实现+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;快餐店点餐服务系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本快餐店点餐服务…

AI学习笔记

目录 专业词汇 AI、NLP和AIGC的关系 涌现能力(Emergent Ability) 专业词汇 专业词汇 (缩写) 英文中文AIArtificial Intelligence人工智能AIGCArtificial Intelligence Generated Content人工智能生成内容PGCProfessional Generated Content专业生成内容UGCUser Generated Co…

【【简单systyem verilog 语言学习使用二--- 新adder加法器 】】

【【简单systyem verilog 语言学习使用二— 新adder加法器 】】 adder.v module addernew(input clk ,input rst_n ,input [2 : 0] in_a ,input [2 : 0] in_b ,input …

曲率定义与三维Mesh曲率估计

曲率定义与三维Mesh曲率估计 二维圆的曲率线的曲率 三维Patch fitting methodsNormal curvature-based methodsTensor averaging methods Estimating Curvatures and Their Derivatives on Triangle Meshes1. Per-Face Curvature Computation2. Coordinate System Transformati…

Dinky控制台:利用SSE技术实现实时日志监控与操作

1、前置知识 1.1 Dinky介绍 实时即未来,Dinky 为 Apache Flink 而生,让 Flink SQL 纵享丝滑。 Dinky 是一个开箱即用、易扩展,以 Apache Flink 为基础,连接 OLAP 和数据湖等众多框架的一站式实时计算平台,致力于流批一体和湖仓一体的探索与实践。 致力于简化Flink任务开…

无人机声学侦测算法详解!

一、算法原理 无人机在飞行过程中&#xff0c;其电机工作、旋翼震动以及气流扰动等都会产生一定程度的噪声。这些噪声具有独特的声学特征&#xff0c;如频率范围、时域和频域特性等&#xff0c;可以用于无人机的检测与识别。声学侦测算法利用这些特征&#xff0c;通过一系列步…