CountDownlatch实现原理
文章目录
- 类图及概要
- 核心方法
- await() 方法
- await(long timeout, TimeUnit unit) 方法
- countDown() 方法
- getCount() 方法
- 总结
类图及概要
CountDownLatch 内部有个计数器,并且这个计数器是递减的 。 下面就通过源码看看 JDK 开发组在何时初始化计数器,在何时递减计数器,当计数器变为 0 时做了什么操作, 多个线程是如何通过计时器值实现同步的 。
从类图可以看出, CountDownLatch 是使用 AQS 实现的 。 通过下面的构造函数,你会发现,实际上是把计数器的值赋给了 AQS 的状态变量 state,也就是这里使用 AQS 的状态值来表示计数器值。
``
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException(“count < 0”);
this.sync = new Sync(count);
}
Sync(int count) {
setState(count);
}
``
核心方法
await() 方法
当线程调 用 CountDownLatch 对象的 await 方法后 , 当前线程会被 阻塞 , 直到下面的情况之一发生才会返回 : 当所有线程都调用了 CountDownLatch 对象的 countDown 方法后,也就是计数器的值为 0 时;其他线程调用了当前线程的 interrupt ()方法中断了当前线程 ,当前线程就会抛出InterruptedException 异常 , 然后返回。
``
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
// 如果线程被中断则抛出异常
if (Thread.interrupted())
throw new InterruptedException();
// 查看当前计数器千直是否为 0 , 为 0 则直接返回 , 否则进入AQS的队列等待
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
// sync类实现的 AQS 的接口
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
``
await() 方法委托 sync 调用 了 AQS 的 acquiresharedInterruptibIy方法 。
该方法 的特点是线程获取资源时可 以被中 断, 并且获取 的资源是共享资源。 acquireSharedlnterruptibly 首先判断当前线程是否己被中断 , 若是则抛出异常,否则调用 sync 实现 的 tryAcquireShared 方法查看当前状态值( 计数器值)是否为 0 , 是则当前线程 的 await() 方法直接返回 , 否 则调用 AQS 的doAcquireSharedlnterruptibly 方法让当前线程阻塞。另外可 以看到,这里tryAcquireShared 传递的 arg 参数没有被用 到, 调用tryAcquireShared 的方法仅仅是为了检查当前状态值是不是为 0 , 并没有调用 CAS 让 当 前状态值减 1 。
await(long timeout, TimeUnit unit) 方法
当线程调用了 CountDownLatch 对象 的该方法后 , 当前线程会被阻塞 , 直到下面的情况之一发生才会返回:当 所有线程都调用了 CountDownLatch 对象 的 countDown 方法后 ,也就是计数器值为 0 时 ,这时候会返 回 true ;设置的 timeout 时间到了,因为超时而返回false ; 其他线程调用了当前线程的 interrupt ( )方法中断了当前线程 , 当前线程会抛出InterruptedException 异常,然后返回。
countDown() 方法
线程调用该方法后 ,计数器的值递减 , 递减后如果计数器值为 0 则唤醒所有因调用await 方 法而被阻塞的线程,否则什么都不做。下面看下 countDown() 方法是 如何调用AQS 的方法的。
``
public void countDown() {
// 委托sync调 用 AQS的方法
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
// 调用 sync 实现的 tryReleaseShared
if (tryReleaseShared(arg)) {
// AQS 的释放资源方法
doReleaseShared();
return true;
}
return false;
}
``
CountDownLatch 的 countDown ( )方法委 托 sync 调用了 AQS 的releaseShared 方法。
re leaseShared 首先调用了 sync 实现的 AQS 的 tryReleaseShared 方法。
``
protected boolean tryReleaseShared(int releases) {
// 循环进行CAS ,直到当前线程成功完成CAS使计数器值(状态值state )减 1并更新到statefor (;;) {int c = getState();// 如果当前状态值为0则直接返回( 1 )if (c == 0)return false;// 使用 CAS让计数器佳减 1 ( 2)int nextc = c-1;if (compareAndSetState(c, nextc))return nextc == 0;}
}
``
如上代码首先获取当前状态值(计数器值) 。 代码 (1) 判断如果当前状态值为 0 则直接返回 false,从而 countDown ( )方法直接返回:否则执行码 (2) 使用 CAS 将计数器值减 1, CAS 失败则循环重试,否则如果当前计数器值为 0 则返回 true,返回 true 说明是最后一个线程调用的 countdown 方法,那么该线程除了让计数器值减 1 外,还需要唤醒因调用 CountDownLatch 的 await 方法而被阻塞的线程,具体是调用 AQS 的 doReleaseShared方法来激活阻塞的线程。这里代码 (1) 貌似是多余的,其实不然,之所以添加代码 (1) 是为了防止当计数器值为 0 后,其他线程又调用了 countDown 方法,如果没有代码 (1) 状态值就可能会变成负数。
getCount() 方法
获取当前计数器的值,也就是 AQS 的 state 的值,在其内部还是调用了 AQS 的 getState 方法来获取 state 的值(计数器当前值)。
``
public long getCount() {
return sync.getCount();
}
int getCount() {
return getState();
}
``
总结
使用 AQS 的状态变量来存放计数器 的值。首先在 初始化CountDownLatch 时设置状态值(计数器值),当多个线程调用 countdown 方法时实际是原子性递减 AQS 的状态值。当线程调用 await 方法后当前线程会被放入 AQS 的阻塞队列等待计数器为 0 再返 回 。其他线程调用 countdown 方法让计数器值递减 1 ,当计数器值变为0 时, 当 前线程还要调用 AQS 的 doReleaseShared 方法来激活由于调用 await() 方法而被阻塞的线程 。
相关文章:
CountDownlatch实现原理
文章目录 类图及概要核心方法await() 方法await(long timeout, TimeUnit unit) 方法countDown() 方法getCount() 方法 总结 类图及概要 CountDownLatch 内部有个计数器,并且这个计数器是递减的 。 下面就通过源码看看 JDK 开发组在何时初始化计数器,在何…...
如何为自己的 PDF 文件添加密码?在线加密 PDF 文件其实更简单
随着信息泄露和数据安全问题的日益突出,保护敏感信息变得尤为重要。加密 PDF 文件是一种有效的手段,可以确保只有授权用户才能访问或修改文档内容。本文将详细介绍如何使用 CleverPDF 在线工具为你的 PDF 文件添加密码保护,确保其安全性。 为…...
现代未来派品牌海报徽标设计无衬线英文字体安装包 THANKS LAB
THANK LAB 是一种高级未来主义的软字体,将时尚的现代设计与光滑圆润的边缘相结合,营造出大胆而平易近人的美感。这款字体非常适合品牌、海报、标题、UI/UX 和科幻主题项目,旨在激发创造力。THANK LAB Futuristic Soft Font 完全支持拉丁字母、…...
基于Flask框架的食谱数据可视化分析系统的设计与实现
【Flask】基于Flask框架的食谱数据可视化分析系统的设计与实现 (完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 在当今数字化时代,信息可视化已成为一种高效的数据理解和传播手段。…...
Mac arm架构使用 Yarn 全局安装 Vue CLI
dgqdgqdeMacBook-Pro spid-admin % vue --version zsh: command not found: vue要使用 Yarn 安装 Vue CLI,你可以执行以下命令: yarn global add vue/cli这个命令会全局安装 Vue CLI,让你可以使用 vue 命令创建、管理 Vue.js 项目。以下是一…...
矩阵-旋转图像
旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。输入:二维数组 输出:void 思路:tempM…...
自用开发的商标和工作小工具!
近日普推知产老杨把个人小站改了版,也把以前业余开发的小工具做了下优化和增加了一些新的小工具,这些在线小工具手机和电脑双适应,普推老杨日常也在用,主要在商标方面和内容制做。 商标名称图样免费生成主要用在可以生成符合商标申…...
基于腾讯云大模型知识引擎×DeepSeek构建八字、六爻赛博算卦娱乐应用
引言 随着DeepSeek的火爆,其强大的思维链让不少人越用越香,由于其缜密的思维和推理能力,不少人开发出了不少花里胡哨的玩法,其中一种就是以八字、六爻为代表的玄学文化正以“赛博玄学”的新形态席卷年轻群体。 针对于八字、六爻…...
八股文实战之JUC:静态方法的锁和普通方法的锁
1、对于staic同步方法锁住的是class类模板(Class对象) 对象是线程(调用者) 调用者只有获取资源的锁才能调用 2、普通同步方法 锁住的资源是class对象 对象是线程(调用者)即: 静态同步方法&a…...
VTK知识学习(42)-基本的图形操作(三)
1、网格平滑 1)概述 现代扫描技术的发展使得获取点云数据不再困难,通过曲面重建技术可以获取表面网格来表示各种复杂的实体。但是点云数据中往往存在噪声,这样得到的重建网格通常都需要进行平滑处理。 拉普拉斯平滑是一种常用的网格…...
代码随想录算法训练营day40(补0208)
买卖股票专栏 1.买卖股票最佳时机 贪心法,好想 题目 121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖…...
python基于深度学习实现遮挡人脸识别系统的详细方案
以下是一个基于深度学习实现遮挡人脸识别系统的详细方案,使用Python语言: 一、需求理解 遮挡人脸识别系统旨在准确识别出即使面部部分被遮挡(如口罩、眼镜等)的人的身份。该系统将利用深度学习技术,结合合适的数据集进行训练,以达到较高的识别准确率。 二、系统架构 …...
【Python爬虫(43)】云端探秘:Python分布式爬虫部署攻略
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
Java集合框架大师课:从青铜到王者的数据结构指南(一)
🚀 Java集合框架大师课:从青铜到王者的数据结构指南(一) 🌟 系列定位:全网最懂小白的JCF实战教程 | 建议搭配IDE边学边练 🎯 学习路线图 第一章:初识JCF江湖 1.1 什么是JCF…...
Vmware虚拟机Ubantu安装Docker、k8s、kuboard
准备工作: 切换用户:su root关闭防火墙: sudo ufw diasble关闭swap: systemctl stop swap.target systemctl status swap.target systemctl disable swap.target #开机禁用 systemctl stop swap.img.swap systemctl status swap.img.swap关闭虚拟交换分区 vim /…...
Java面试——Tomcat
优质博文:IT_BLOG_CN 一、Tomcat 顶层架构 Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务。Service主要包含两个部分:Connector和…...
游戏引擎学习第113天
仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板:优化的基本过程 在游戏编程中,优化是一个非常重要的学习内容,尤其是想要成为专业开发者时。优化的核心是理解代码的执行速度,以及如何提升其性能。在这个阶段,已经…...
【EB-02】TC397 Tresos 最小工程配置
TC397 Tresos 最小工程配置 1. 新建demo 工程2. 配置消除错误2.1 ResourceM 设置2.2 McalLib模块配置3. 生成代码3.1 校验工程3.2 生成代码1. 新建demo 工程 新建工程 设置工程名称 选择芯片型号 选择添加模块 得到最小工程需求模块 2. 配置消除错误 2.1 ResourceM 设置 设置芯…...
深入理解WebSocket接口:如何使用C++实现行情接口
在现代网络应用中,实时数据传输变得越来越重要。通过WebSocket,我们可以建立一个持久连接,让服务器和客户端之间进行双向通信。这种技术不仅可以提供更快的响应速度,还可以减少不必要的网络流量。本文将详细介绍如何使用C来实现We…...
前端面试题
以下是一些前端面试题: 一、HTML/CSS部分 如何实现一个元素的背景颜色渐变效果,并且在不同浏览器中保持兼容性? 答案: 对于现代浏览器,可以使用标准的CSS渐变语法。 线性渐变示例(从左到右,红色到蓝色):background: linear - gradient(to right, red, blue);径向渐变…...
Win11 24h2 不能正常使用ensp的问题(已解决)
因为Win11 24h2的内核大小更改,目前virtualbox在7.1.4中更新解决了。所以Win11 24H2系统版本无法使用 5.x.xx的virtualbox版本,virtualbox对于这个5.x.xx版本早已停止维护,所以这个以后不会有调整。 对应的报错代码是 virtualbox错误代码&…...
Hyper-V初探
听说window自带虚拟机,小窃喜了一下,这样就不用下载第三方虚拟机软件了:VMware或者Oracle VirtualBox,但是本地搜索一看,发现没有安装,百度了一下说家庭中文版是个阉割版的系统,只有教育版&…...
IP协议
IP协议介绍 IP地址=目标网络+目标主机 IP协议是网络层协议 IP报头格式 [IP报头图片] IP报头解析 4 位版本号(version): 指定 IP 协议的版本, 对于 IPv4 来说, 就是 4. 4 位头部长度(header length): IP 头部的长度是多少个 32bit, 也就是 length 4…...
Django Admin: 实现基于数据库实际值的动态过滤器
在 Django Admin 中,我们经常需要使用 list_filter 来为管理界面添加过滤功能。然而,有时我们希望过滤器能够动态地反映数据库中的实际值,而不是依赖于预定义的选项。本文将介绍如何实现一个基于数据库实际值的动态过滤器,以 ECR 仓库的区域过滤为例。 问题背景 在管理 E…...
overflow-x: auto 使用鼠标实现横向滚动,区分触摸板和鼠标滚动事件的方法
假设一个 div 的滚动只设置了 overflow-x: auto 我们发现使用鼠标的滚轮是无法左右滚动的,但是使用笔记本电脑的触摸板,或者在移动设备上是可以滚动的。所以我们需要兼容一下鼠标的横向滚动功能。 我们可以监控 wheel 事件,然后根据位置来计…...
DPVS-2:单臂负载均衡测试
上一篇编译安装了DPVS,这一篇开启DPVS的负载均衡测试 : 单臂 FULL NAT模式 拓扑-单臂 单臂模式 DPVS 单独物理机 CLINET,和两个RS都是另一个物理机的虚拟机,它们网卡都绑定在一个桥上br0 , 二层互通。 启动DPVS …...
宇树科技13家核心零部件供应商梳理!
2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…...
sqli-labs之Kali搭建靶场环境
背景: SQL注入是一种常见的Web安全漏洞,攻击者可以通过该漏洞在应用程序中执行任意的SQL命令。为了帮助开发者和安全研究人员更好地理解和防范SQL注入攻击,sqli-labs应运而生。它是一个开源项目,提供了一系列的SQL注入练习环境&a…...
Kafka在Windows系统使用delete命令删除Topic时出现的问题
在使用Windows的Kafka时,想要删除某一个主题,发现使用了delete之后会一直报警告。下面是我发现错误之后重新实测的Bug 先创建2个topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test1 --createkafka-topics.bat --bootstrap-serve…...
JVM 面试题相关总结
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
动态记忆网络 DeepMind的MEMO架构允许在推理时动态读写记忆矩阵,记忆容量提升40倍
为了更深入地理解 MEMO 架构的意义,我来详细解读一下,并探讨它在实际应用中的潜力: MEMO 架构的核心思想 MEMO (Memorizing over Memorized) 架构的核心思想是 “层叠记忆”。 传统的记忆网络通常只有一个外部记忆模块,而 MEMO …...
go 并发 gorouting chan channel select Mutex sync.One
goroutine // head: 前缀 index:是一个int的指针 func print(head string, index *int) {for i : 0; i < 5; i {// 指针对应的int *indexfmt.Println(*index, head, i)// 暂停1stime.Sleep(1 * time.Second)} }/* Go 允许使用 go 语句开启一个新的运…...
【STM32 基于PID的闭环电机控制系统】
STM32 基于PID的闭环电机控制系统 目录 STM32 基于PID的闭环电机控制系统一、PID算法在STM32F103C8T6中的实现思路二、代码实现与解释三、PID算法的调试与优化四、总结 一、PID算法在STM32F103C8T6中的实现思路 基本概念 • 目标 :通过PID算法调节电机的转速&#…...
Linux命令后双减号符(--)的含义
个人博客地址:Linux命令后双减号符(--)的含义 | 一张假钞的真实世界 Unix/Linux下各种命令的参数,都是以减号符(-)后面跟单字符参数,比如-r)或者双减号符(--)…...
QT闲记-工具栏
工具栏通常用来放置常用的操作按钮,如QPushButton,QAction等。可以放置在顶部,底部,左侧,右侧,并且支持拖曳,浮动。 1、创建工具栏 通常通过QMainWindow 提供的addToolBar()来创建,它跟菜单栏一样,如果需要工具栏,一般情况下,我们设置这个类的基类为QMainWindow。 …...
Linux中ps -ef命令详解
ps -ef 是一个常用的 Unix/Linux 命令,用于显示当前系统中所有进程的详细信息。具体来说,ps 是 "process status" 的缩写,用于查看进程的状态。-ef 是 ps 命令的选项组合,用于指定输出的格式和内容。 选项解释…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter20-JavaScript API
二十、JavaScript API JavaScript API 随着 Web 浏览器能力的增加,其复杂性也在迅速增加。从很多方面看,现代 Web 浏览器已经成为构建于诸多规范之上、集不同 API 于一身的“瑞士军刀”。浏览器规范的生态在某种程度上是混乱而无序的。一些规范如 HTML5&…...
详解分布式ID实践
引言 分布式ID,所谓的分布式ID,就是针对整个系统而言,任何时刻获取一个ID,无论系统处于何种情况,该值不会与之前产生的值重复,之后获取分布式ID时,也不会再获取到与其相同的值,它是…...
Linux 高级篇 日志管理、定制自己的Linux系统、备份与恢复
一、日志管理 (1)基本介绍 日志文件是重要的系统信息文件,记录了如用户登录、系统启动、系统安全、邮件及各种服务等相关重要系统事件在安全方面,日志也至关重要,它能记录系统日常发生的各类事情,可用于检…...
uniapp中@input输入事件在修改值只有第一次有效的问题解决
在uniapp中使用输入框,要求输入不超过7个字,所以需要监听输入事件,当每次输入文字的时候,就把输入的值截断,取前7个值。但是在input事件中,重新赋值的值发生了变化,但是页面上的还是没有变&…...
单片机 code RO-data RW-data ZI-data以及OTA学习
带着问题去学习:这些数据是什么?分别放在哪里, 是什么:我个人的理解 code 和RO-data 分别是代码和只读数据,RW-data以及ZI-data分别是读写数据和初始化数据。 codeRO-data的大小正好是所占用ROM的大小,RO…...
Jenkins 视图(View)
Jenkins 视图(View) 一、视图是什么 Jenkins 视图(View) 如下图中 All、Apps 都是 Jenkisn 中的 View 左侧如果有 New View 或者 点击 All 这一行最右侧的 号,都可以创建视图 二、视图(View)的作用 点击最左侧的 All 可以看到所有的任务 随着项目不断发展&am…...
【Deepseek+Dify】wsl2+docker+Deepseek+Dify部署本地大模型知识库问题总结
wsl2dockerDeepseekDify部署本地大模型知识库问题总结 基于ollama部署本地文本模型和嵌入模型 部署教程 DeepSeekdify 本地知识库:真的太香了 问题贴:启动wsl中docker中的dify相关的容器 发现postgre服务和daemon服务一直在重启,导致前端加…...
实战解析传统发电站智能化改造-第二期(带图带教程)
传统发电站的智能化改造,如同为老工匠配备高科技工具,提升效率与精准度。改造后的发电站兼具传统与智能,更高效、环保,适应现代能源需求。智慧系统搭建平台是连接感知层和应用层的桥梁,将原始数据转化为有价值的信息&a…...
鸿蒙5.0实战案例:基于自定义注解和代码生成实现路由框架
往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录) ✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~ ✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ ✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景&#…...
项目设置内网 IP 访问实现方案
在我们平常的开发工作中,项目开发、测试完成后进行部署上线。比如电商网站、新闻网站、社交网站等,通常对访问不会进行限制。但是像企业内部网站、内部管理系统等,这种系统一般都需要限制访问,比如内网才能访问等。那么一个网站应…...
单片机 Bootloade与二进制文件的生成
单片机的 Bootloader 是一种特殊的程序,负责在单片机上电后初始化硬件、更新用户应用程序(固件),并将控制权移交给用户程序。以下是其运行机制和关键流程的详细说明: 1、单片机 Bootloader 的核心作用 固件更新&…...
open webui 部署 以及解决,首屏加载缓慢,nginx反向代理访问404,WebSocket后端服务器链接失败等问题
项目地址:GitHub - open-webui/open-webui: User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 选择了docker部署 如果 Ollama 在您的计算机上,请使用以下命令 docker run -d -p 3000:8080 --add-hosthost.docker.internal:host-gatewa…...
深度学习每周学习总结Y1(Yolov5 调用官方权重进行检测 )
🍨 本文为🔗365天深度学习训练营 中的学习记录博客Y1中的内容 🍖 原作者:K同学啊 | 接辅导、项目定制 ** 注意该训练营出现故意不退押金,恶意揣测偷懒用假的结果冒充真实打卡记录,在提出能够拿到视频录像…...
HTML项目一键打包工具:HTML2EXE 最新版
HTML2EXE 工具可以一键打包生成EXE可执行文件。可以打包任意HTML项目或者是一个网址为单个EXE文件,直接打开即可运行。支持KRPano全景VR项目、WebGL游戏项目、视频播放、,课件打包、网址打包等。 一、功能特点 类别序号功能标题1支持程序图标自定义(支持…...