当前位置: 首页 > article >正文

【JUC并发 | 第九篇】Semaphore 和 CountDownLatch

目录SemaphoreSemaphore 原理CountDownLatchCountDownLatch 作用CountDownLatch 原理【JUC并发 | 第八篇】AQS的底层原理https://blog.csdn.net/h52412224/article/details/159159242?spm1001.2014.3001.5502【JUC并发 | 第七篇】简析Future 和 CompletableFuture类https://blog.csdn.net/h52412224/article/details/159078192【JUC并发 | 第六篇】深入理解线程池https://blog.csdn.net/h52412224/article/details/159043558?spm1001.2014.3001.5502SemaphoreSemaphore 原理一、核心定位Semaphore 是 Java 并发包中用于控制并发访问线程数的同步工具底层完全基于 AQS 的共享模式实现——核心是通过 AQS 的state变量表示“可用许可数”利用 AQS 共享模式的线程排队、阻塞/唤醒机制实现多线程对许可的获取与释放。二、Semaphore底层核心实现1. 核心关联Semaphore与AQS的映射关系Semaphore 内部封装了一个继承 AQS 的同步器类Sync并分为公平版FairSync和非公平版NonfairSync核心映射关系Semaphore概念AQS底层实现许可数AQS 的state变量初始值由 Semaphore 构造函数指定如new Semaphore(3)则state3获取许可调用 AQS 的acquireShared()核心是tryAcquireShared()CAS 减少 state释放许可调用 AQS 的releaseShared()核心是tryReleaseShared()CAS 增加 state线程排队阻塞竞争许可失败的线程封装为 Node 节点加入 AQS 的 CLH 队列等待被唤醒2. 核心方法的底层实现1获取许可acquire()方法Semaphore 的acquire()本质是调用 AQS 的acquireSharedInterruptibly(1)核心逻辑在tryAcquireShared()中非公平版默认// NonfairSync 的 tryAcquireShared 实现 protected int tryAcquireShared(int acquires) { return nonfairTryAcquireShared(acquires); } final int nonfairTryAcquireShared(int acquires) { for (;;) { // 自旋 CAS // 1. 获取当前可用许可数 int available getState(); // 2. 计算获取后剩余许可数 int remaining available - acquires; // 3. CAS 修改 state剩余许可≥0 则修改成功否则失败 if (remaining 0 || compareAndSetState(available, remaining)) { return remaining; } } }返回值含义≥0表示获取许可成功0表示失败进入 AQS 队列阻塞。公平版仅多一步“检查队列是否有等待线程”避免新线程插队protected int tryAcquireShared(int acquires) { for (;;) { // 公平性检查如果队列有等待线程直接返回-1放弃竞争 if (hasQueuedPredecessors()) { return -1; } // 后续逻辑与非公平版一致 int available getState(); int remaining available - acquires; if (remaining 0 || compareAndSetState(available, remaining)) { return remaining; } } }2释放许可release()方法Semaphore 的release()调用 AQS 的releaseShared(1)核心逻辑在tryReleaseShared()中protected final boolean tryReleaseShared(int releases) { for (;;) { // 自旋 CAS // 1. 获取当前许可数 int current getState(); // 2. 计算释放后许可数 int next current releases; // 边界检查避免许可数溢出 if (next current) { throw new Error(Maximum permit count exceeded); } // 3. CAS 修改 state 成功则返回 true唤醒队列等待线程 if (compareAndSetState(current, next)) { return true; } } }释放许可成功后AQS 会唤醒 CLH 队列中等待的线程让它们重新竞争许可。3.Semaphore核心执行流程以new Semaphore(2)初始 2 个许可为例拆解完整流程场景线程 A、B、C 同时调用 acquire() 获取 1 个许可。 步骤 1线程 A 执行 tryAcquireShared(1)CAS 将 state 从 2→1返回 1≥0获取许可成功 步骤 2线程 B 执行 tryAcquireShared(1)CAS 将 state 从 1→0返回 0≥0获取许可成功 步骤 3线程 C 执行 tryAcquireShared(1)计算 remaining0-1-1CAS 失败返回 -1 步骤 4线程 C 进入 AQS 的 CLH 队列调用 LockSupport.park() 阻塞 步骤 5线程 A 执行 release()CAS 将 state 从 0→1返回 trueAQS 唤醒队列中的线程 C 步骤 6线程 C 被唤醒重新执行 tryAcquireShared(1)CAS 将 state 从 1→0获取许可成功退出队列。四、补充Semaphore与 ReentrantLock 的底层差异特性SemaphoreReentrantLockAQS模式共享模式独占模式state 含义可用许可数锁的重入次数竞争结果多线程可同时获取资源仅一个线程能获取资源核心方法tryAcquireShared/releaseSharedtryAcquire/release总结Semaphore信号量的底层完全基于 AQS 的共享模式实现核心逻辑如下许可数管理Semaphore 的“可用许可数”对应 AQS 的state变量初始许可数由构造函数指定获取许可调用acquire()时底层执行 AQS 的acquireShared()通过tryAcquireShared()自旋 CAS 减少state——剩余许可≥0 则获取成功否则线程入队阻塞公平版会先检查队列是否有等待线程非公平版直接抢许可释放许可调用release()时底层执行 AQS 的releaseShared()通过tryReleaseShared()自旋 CAS 增加state成功后唤醒 CLH 队列中等待的线程让其重新竞争许可核心特点支持多线程同时获取许可共享模式可灵活控制并发访问的线程数常用于限流、资源池控制等场景。CountDownLatchCountDownLatch 作用CountDownLatch 原理一、核心定位CountDownLatch 是 Java 并发包中用于等待多个线程完成任务的同步工具底层完全基于 AQS 的共享模式实现——核心是通过 AQS 的state变量表示“剩余待完成的任务数”利用 AQS 共享模式的线程排队、阻塞/唤醒机制实现“主线程等待所有子线程完成后再执行”的逻辑。二、CountDownLatch 底层核心实现1. 核心关联CountDownLatch 与AQS的映射关系CountDownLatch 内部封装了一个继承 AQS 的同步器类Sync无公平/非公平之分核心映射关系CountDownLatch 概念AQS底层实现倒计时数AQS 的state变量由构造函数指定如new CountDownLatch(3)则state3等待线程阻塞调用await()时底层执行 AQS 的acquireSharedInterruptibly(1)竞争失败则入队阻塞计数器减 1调用countDown()时底层执行 AQS 的releaseShared(1)CAS 减少 state唤醒等待线程当 state 减到 0 时AQS 唤醒所有阻塞在队列中的线程2. 核心方法的底层实现1初始化CountDownLatch(int count)构造函数直接将传入的“倒计时数”赋值给 AQS 的state且state一旦初始化无法重置CountDownLatch 是一次性的public CountDownLatch(int count) { if (count 0) throw new IllegalArgumentException(count 0); this.sync new Sync(count); // Sync 是内部 AQS 子类 } // 内部 Sync 类的构造 Sync(int count) { setState(count); // 调用 AQS 的 setState() 给 state 赋值 }2等待线程阻塞await() 方法await()是 CountDownLatch 的核心等待方法底层调用 AQS 的acquireSharedInterruptibly(1)核心逻辑在tryAcquireShared()中// CountDownLatch 的 await() public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } // 内部 Sync 重写的 tryAcquireShared核心逻辑 protected int tryAcquireShared(int acquires) { // 核心规则state0 时返回 1获取成功无需阻塞否则返回 -1失败入队阻塞 return (getState() 0) ? 1 : -1; }当线程调用await()时会循环执行tryAcquireShared()如果state≠0任务未完成返回 -1线程被封装为 Node 节点加入 AQS 的 CLH 队列调用LockSupport.park()阻塞如果state0所有任务完成返回 1线程直接执行无需阻塞。3计数器减 1countDown() 方法countDown()是触发倒计时的核心方法底层调用 AQS 的releaseShared(1)核心逻辑在tryReleaseShared()中// CountDownLatch 的 countDown() public void countDown() { sync.releaseShared(1); } // 内部 Sync 重写的 tryReleaseShared核心逻辑 protected boolean tryReleaseShared(int releases) { for (;;) { // 自旋 CAS 保证原子性多线程同时 countDown 不冲突 int c getState(); // 1. 如果 state 已经为 0直接返回 false无需处理 if (c 0) return false; // 2. 计数器减 1 int nextc c - 1; // 3. CAS 修改 state保证原子性 if (compareAndSetState(c, nextc)) { // 关键只有当 state 减到 0 时返回 true触发 AQS 唤醒所有等待线程 return nextc 0; } } }每次调用countDown()都会通过 CAS 将state减 1只有当state从 1 减到 0 时tryReleaseShared()返回 trueAQS 才会唤醒 CLH 队列中所有阻塞的线程。3. CountDownLatch 核心执行流程以new CountDownLatch(2)等待 2 个子线程完成为例拆解完整流程场景主线程调用 await() 等待子线程 1、子线程 2 执行任务后调用 countDown()。 步骤 1CountDownLatch 初始化state2 步骤 2主线程调用 await()执行 tryAcquireShared()state2≠0返回 -1主线程入队阻塞 步骤 3子线程 1 完成任务调用 countDown()CAS 将 state 从 2→1nextc1≠0返回 false无唤醒操作 步骤 4子线程 2 完成任务调用 countDown()CAS 将 state 从 1→0nextc0返回 true 步骤 5AQS 收到返回的 true唤醒队列中阻塞的主线程 步骤 6主线程被唤醒重新执行 tryAcquireShared()state0返回 1主线程退出阻塞继续执行。public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { // 初始化计数器值为3代表3个任务 CountDownLatch latch new CountDownLatch(3); // 启动3个线程执行任务 for (int i 1; i 3; i) { new Thread(() - { try { System.out.println(Thread.currentThread().getName() 执行任务); Thread.sleep(1000); // 模拟任务执行时间 } finally { // 任务完成计数器减1 latch.countDown(); } }, 线程 i).start(); } // 主线程等待所有任务完成 latch.await(); System.out.println(所有子任务完成主线程执行汇总逻辑); } }总结CountDownLatch 的底层完全基于 AQS 的共享模式实现核心逻辑如下计数器管理CountDownLatch 的“倒计时数”对应 AQS 的state变量由构造函数初始化且一旦初始化无法重置等待阻塞调用await()时底层执行 AQS 的acquireSharedInterruptibly()通过tryAcquireShared()判断 state 是否为 0——非 0 则线程入 AQS 队列阻塞0 则直接执行倒计时触发调用countDown()时底层执行 AQS 的releaseShared()通过自旋 CAS 将 state 减 1只有当 state 减到 0 时才返回 true触发 AQS 唤醒所有阻塞的等待线程核心特点CountDownLatch 是一次性的state 减到 0 后无法重置支持多线程等待适用于“主线程等待多个子线程完成任务”的场景。补充CountDownLatch 与 Semaphore 的底层差异特性CountDownLatchSemaphorestate 含义剩余倒计时数0 触发唤醒可用许可数核心逻辑等待 state 变为 0竞争有限的许可数复用性一次性state 到 0 失效可复用释放后许可恢复唤醒逻辑state0 时唤醒所有线程释放许可时唤醒单个线程上述内容也同步在我的飞书欢迎访问https://my.feishu.cn/wiki/QLauws6lWif1pnkhB8IcAvkhncc?fromfrom_copylink如果我的内容对你有帮助请点赞评论收藏。创作不易你们的支持就是我坚持下去的动力

相关文章:

【JUC并发 | 第九篇】Semaphore 和 CountDownLatch

目录 Semaphore Semaphore 原理 CountDownLatch CountDownLatch 作用 CountDownLatch 原理 【JUC并发 | 第八篇】AQS的底层原理https://blog.csdn.net/h52412224/article/details/159159242?spm1001.2014.3001.5502 【JUC并发 | 第七篇】简析Future 和 CompletableFutur…...

Immutables 性能优化技巧:预哈希、单例模式和内部机制

Immutables 性能优化技巧:预哈希、单例模式和内部机制 【免费下载链接】immutables Annotation processor to create immutable objects and builders. Feels like Guavas immutable collections but for regular value objects. JSON, Jackson, Gson, JAX-RS integ…...

递归魔法:从排列组合到算法优化

1. 递归与排列组合的奇妙邂逅 第一次接触递归解决全排列问题时,我盯着屏幕上的代码看了整整半小时。那感觉就像在玩俄罗斯套娃——每次打开一个函数,里面又调用了自己。后来在实际项目中反复使用才发现,递归处理排列组合简直是量身定制的解决…...

基于大模型的政务问答系统:建设、运维与成效

在数字政府建设迈入“智能化深耕”的今天,传统政务问答模式的痛点日益凸显——人工坐席压力大、咨询高峰响应滞后、政策解读不精准、跨部门咨询衔接不畅,群众和企业办事“问不清、等得久、跑多次”的问题难以彻底解决。而大模型技术的崛起,凭…...

基于径向基RBF神经网络的故障分类与故障诊断matlab程序代码详解及示例

径向基RBF神经网络的故障分类与故障诊断matlab 程序代码RBF神经网络故障分类与诊断系统:设计思路、功能全景与最佳实践——一份面向工程团队的“黑盒”技术指南------------------------------------------------ 引言 旋转机械、电力电子、流程工业等场景对“零停机…...

Kylin V10本地源搭建全攻略:从reposync到Apache配置一步到位

Kylin V10本地源搭建全攻略:从reposync到Apache配置一步到位 在离线环境中维护服务器系统时,最头疼的莫过于软件包的依赖管理。上周我接手了一个军工企业的内网服务器集群,所有设备都运行Kylin V10系统,但无法连接外网更新软件。经…...

3步打造无广告音乐体验:xManager高效管理指南

3步打造无广告音乐体验:xManager高效管理指南 【免费下载链接】xManager Ad-Free, New Features & Freedom 项目地址: https://gitcode.com/GitHub_Trending/xm/xManager 还在为音乐应用广告弹窗烦恼?通勤路上想听首歌却被30秒广告打断&#…...

ArchUnit架构层测试终极指南:分层架构与洋葱架构验证

ArchUnit架构层测试终极指南:分层架构与洋葱架构验证 【免费下载链接】ArchUnit A Java architecture test library, to specify and assert architecture rules in plain Java 项目地址: https://gitcode.com/gh_mirrors/ar/ArchUnit ArchUnit是一个强大的J…...

EasyFloat实战案例:从零构建完整的悬浮窗应用

EasyFloat实战案例:从零构建完整的悬浮窗应用 【免费下载链接】EasyFloat 🔥 EasyFloat:浮窗从未如此简单(Android可拖拽悬浮窗口,支持页面过滤、自定义动画,可设置单页面浮窗、前台浮窗、全局浮窗&#xf…...

Ruoyi+WebSocket实战:如何绕过安全配置实现即时通讯功能

Ruoyi框架中WebSocket安全配置的深度实践指南 引言:当实时通讯遇上安全框架 在基于Ruoyi框架开发企业级应用时,实时通讯功能的需求日益普遍。想象这样一个场景:你的团队协作平台需要即时消息通知,客服系统要求实时对话能力&#x…...

3D打印文件转换不再头疼:Blender 3MF插件让你的创意完美输出 [特殊字符]

3D打印文件转换不再头疼:Blender 3MF插件让你的创意完美输出 🚀 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 还在为3D打印文件格式转换而烦恼吗…...

【数据分析】基于机器学习增强策略对燃烧不稳定预测进行不确定性量化附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…...

MiUnlockTool完全解析:小米设备Bootloader解锁终极指南

MiUnlockTool完全解析:小米设备Bootloader解锁终极指南 【免费下载链接】MiUnlockTool MiUnlockTool developed to retrieve encryptData(token) for Xiaomi devices for unlocking bootloader, It is compatible with all platforms. 项目地址: https://gitcode.…...

gabs核心功能深度解析:数组操作、路径查询与数据修改

gabs核心功能深度解析:数组操作、路径查询与数据修改 【免费下载链接】gabs For parsing, creating and editing unknown or dynamic JSON in Go 项目地址: https://gitcode.com/gh_mirrors/ga/gabs gabs是一款专为Go语言设计的JSON处理库,能够帮…...

VR消防安全学习机|沉浸式体验守护生命安全的新方式

在现代社会,消防安全教育已经成为全民必修课。从校园到社区,从企业到公共场所,火灾防范和应急自救的知识普及显得尤为重要。传统的宣讲、板报、视频虽然能传递知识,但缺乏真实感和参与度。而随着虚拟现实技术(VR&#…...

永磁同步电机的无感控制里有个头疼的问题:转速抖得跟筛糠似的。传统滑模观测器用反正切算角度,差分得转速,这招在实验室还行,真上工程现场就容易翻车

基于PLL的SMO滑模观测器算法,永磁同步电机无传感器矢量控制,跟基于反正切的SMO做对比,可以有效消除转速的抖动。咱先看老方法怎么玩的。滑模观测器吐出反电动势ealpha和ebeta后,代码通常是这样的: // 传统反正切法 flo…...

Reflex安全指南:防止无限循环与权限管理的最佳实践

Reflex安全指南:防止无限循环与权限管理的最佳实践 【免费下载链接】reflex Run a command when files change 项目地址: https://gitcode.com/gh_mirrors/ref/reflex Reflex是一款强大的文件监控工具,能够在文件变化时自动运行指定命令&#xff…...

5个开源工具打造系统性能优化全方案:从问题定位到长效管理

5个开源工具打造系统性能优化全方案:从问题定位到长效管理 【免费下载链接】Atlas 🚀 An open and lightweight modification to Windows, designed to optimize performance, privacy and security. 项目地址: https://gitcode.com/GitHub_Trending/a…...

三阶线性自抗扰控制器:Simulink仿真模型,动态响应迅速,参数调节方便,已封装可拖拽使用...

三阶线性自抗扰控制器 动态响应良好 迅速跟踪指令值 simulink 仿真模型 已封装 可直接拖拽使用 参数调节方便 本人已在多个仿真中应用 效果良好 默认发送19b 记得留下matlab版本号三阶线性自抗扰控制器这玩意儿在工程仿真里贼好用,特别是需要快速跟踪指令的场景。前…...

微信安装包时光机:3步搭建个人版本档案馆

微信安装包时光机:3步搭建个人版本档案馆 【免费下载链接】wechat-versions 保存微信历史版本 项目地址: https://gitcode.com/gh_mirrors/we/wechat-versions 在数字化时代,软件更新迭代速度日益加快,微信作为日常沟通的重要工具&…...

解决Thingsboard数据下发难题:自定义RPC请求格式的3种方法(含源码修改指南)

ThingsBoard数据下发实战:3种自定义RPC请求格式的工程化解决方案 在物联网平台的实际部署中,数据格式的兼容性问题就像一把双刃剑——既考验着系统的灵活性,又决定着集成的成败。最近在为一个智能农业项目部署ThingsBoard平台时,我…...

Chrome开发者工具实战:5分钟搞定网站Cookie提取与注入(附常见问题排查)

Chrome开发者工具实战:5分钟搞定网站Cookie提取与注入(附常见问题排查) 每次调试需要登录状态的页面时,反复输入账号密码是不是让你抓狂?作为前端开发者,掌握Cookie的快速提取与注入技巧能极大提升调试效率…...

游戏开发必看:透视投影与正交投影的5个核心差异及适用场景

游戏开发必看:透视投影与正交投影的5个核心差异及适用场景 在3D游戏开发中,投影方式的选择直接影响着玩家的视觉体验和游戏性能。就像摄影师需要根据拍摄对象选择不同镜头一样,游戏开发者也需要根据场景需求在透视投影和正交投影之间做出明智…...

Modularization-examples社区与支持:如何参与贡献并获取专家帮助

Modularization-examples社区与支持:如何参与贡献并获取专家帮助 【免费下载链接】modularization-examples 代码防腐实用技术 项目地址: https://gitcode.com/gh_mirrors/mo/modularization-examples modularization-examples是一个专注于代码防腐实用技术的…...

AG-Grid合并单元格实战:手把手教你实现动态行合并与样式定制

AG-Grid高级合并单元格实战:动态行合并与条件样式全解析 1. 企业级表格的合并需求场景 在金融报表、供应链管理等企业级应用中,数据表格往往需要展示具有层级关系的结构化数据。比如销售数据按地区分组、员工信息按部门归类等场景,合并单元格…...

清音听真技术解析:Qwen3-ASR-1.7B语义理解层如何提升长句逻辑连贯性

清音听真技术解析:Qwen3-ASR-1.7B语义理解层如何提升长句逻辑连贯性 1. 语音识别技术的演进挑战 语音识别技术从早期的简单指令识别发展到如今的复杂场景理解,经历了巨大的技术飞跃。在真实应用场景中,我们经常遇到这样的挑战:说…...

Hunyuan-MT Pro企业落地:支持LDAP集成的多租户翻译SaaS私有化部署

Hunyuan-MT Pro企业落地:支持LDAP集成的多租户翻译SaaS私有化部署 1. 企业级翻译需求与挑战 在全球化业务快速发展的今天,企业面临着多语言沟通的严峻挑战。跨国团队协作、海外客户服务、多语言文档处理等场景,都对翻译工具提出了更高要求&…...

ECharts图表美化技巧:用markLine打造专业级警戒线和动态箭头效果

ECharts图表美化技巧:用markLine打造专业级警戒线和动态箭头效果 在数据可视化领域,ECharts凭借其强大的功能和灵活的配置选项,已成为众多开发者和设计师的首选工具。其中,markLine(标记线)功能常被用于绘制…...

如何用XcodeBenchmark选择最佳Mac设备:完整成本效益分析教程

如何用XcodeBenchmark选择最佳Mac设备:完整成本效益分析教程 【免费下载链接】XcodeBenchmark XcodeBenchmark measures the compilation time of a large codebase on iMac, MacBook, and Mac Pro 项目地址: https://gitcode.com/gh_mirrors/xc/XcodeBenchmark …...

PPT高手都不知道的骚操作:用形状组合画出专业机器学习示意图(避坑指南)

PPT高手都不知道的骚操作:用形状组合画出专业机器学习示意图(避坑指南) 在技术演示和学术汇报中,一张清晰的示意图往往胜过千言万语。但很多工程师和讲师都面临同样的困境:既没有专业设计软件的使用经验,又…...