根据AQS推测CountDownLatch及源码分析

AQS中的同步器CountDownLatch 在Java并发编程中,CountDownLatch是一个简单易用但又功能强大的同步工具类。它可以理解为一个“倒计时门闩”,允许一个或多个线程等待其他线程完成操作后再继续执行。 阅读详情

    CountDownLatch实现的是AQS中的共享模式。一般用于线程间的协作,如主线程创建了多个线程去做别的工作,等到这些线程都执行完毕了才能往下执行,这时候就可以用countDownLatch来实现。

public class CountDownLatch2 {

    public static void main(String[] args) throws InterruptedException {
        final CountDownLatch latch =new CountDownLatch(5);
        final AtomicInteger in=new AtomicInteger(1);
        for(int i=0;i<5;i++){
            Thread t=new Thread(new Runnable() {

                @Override
                public void run() {
                    System.out.println("线程"+in.getAndIncrement()+"做完了准备工作");
                    latch.countDown();
                }
            });
            t.start();
        }
        System.out.println("等待其他线程都执行完毕准备工作");
        latch.await();
        System.out.println("所有准备工作已经完毕,可以往下执行");
    }

}

输出:
线程1做完了准备工作
线程3做完了准备工作
等待其他线程都执行完毕准备工作
线程4做完了准备工作
线程2做完了准备工作
线程5做完了准备工作
所有准备工作已经完毕,可以往下执行

    可以看到,latch.await()会阻塞到所有线程都调用了latch.countdown()之后才能往下执行。
    我们就来研究一下CountDownLatch是怎么实现的呢?

    先放出根据http://blog.youkuaiyun.com/FoolishAndStupid/article/details/75676027 中得到的简单的结论:

    我们又知道,countdownlatch.await()会阻塞当前线程直到所有线程都调用了countdown()之后。根据图1可以推论出await()方法调用的是acquireShared()方法,然后latch自定义的tryAcquireShared()方法,当stata!=0的时候,会返回<0,这样,await()方法就会阻塞。

    那么当所有线程都调用了countdown()之后,阻塞的线程又会唤醒。我们可以继续推论出countdown()方法其实是调用的tryReleaseShared()方法。当state=0时,tryReleaseShared()返回true,就可以成功唤醒阻塞的线程了。
    那我们来看一下到底是不是呢?
    先看看await()方法:

     countdown.await()

public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    再往下看:

public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

    可以看到,其实就是调用自定义同步器中实现的tryAcquireShared()方法,如果返回值<0,则将线程阻塞。
    那再来看看自定义同步器中的tryAcquireShared():

public int tryAcquireShared(int acquires) {
            return getState() == 0? 1 : -1;
        }

    果然,跟我们前面的推测一样,当state!=0的时候就返回-1,从而通过AQS来阻塞线程。

countdown.release()方法:

 public void countDown() {
        sync.releaseShared(1);
    }

    releaseShared是AQS中已经实现的方法,进来看看:

public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

    可以看到,它也是调用的自定义同步器实现的tryReleaseShared()方法:

 public boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

    跟我们前面推测的一样,当state=0的时候,就会返回true,从而唤醒后继节点,也就是调用await()方法的线程。

    所以总结起来就是,countDownLatch中自定义同步器实现了AQS的共享模式,实现了tryAcquireShared()方法和tryReleaseShared()方法。其中tryAcquireShared()方法被await()方法调用,在state!=0的时候返回-1(表示资源获取失败),从而实现阻塞调用线程的目的。
    而tryReleaseShared()方法则是被countdown()方法调用,在state=0的时候返回true,从而唤醒调用await()方法而阻塞的节点。

架构面试-分布式存储系统HA高可用原理及应用案例实战 本文详细介绍了CountDownLatch、CyclicBarrier、Semaphore及其在分布式存储系统高可用中的应用案例 阅读详情

相关推荐

CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

CountDownLatch 和 CyclicBarrier 为线程同步的辅助工具,通过它可以做到使一条线程一直阻塞等待,直到其他线程完成其所处理的任务。

CountDownLatch源码分析

JAVA后端开发知识总结(持续更新…) CountDownLatch源码分析 文章目录CountDownLatch源码分析零、前言一、概述二、常用方法2.1 countDown()——tryReleaseShared()的实现2.2 await()——tryAcquireShared()的实现 零、前言 在阅读本篇文章前,建议先学习下面两篇文章: 《AQS源码解析》 《await和signal源码解析》 一、概述   CountDownLatch 是为了解决某些操作只能在一组操作全部执行完成后才能执.

weixin_43415481的博客 314

Tomcat源码:Acceptor与Poller、PollerEvent

前文中我们介绍到NioEndpoint的start方法启动了Acceptor与Poller这两个异步线程来处理连接请求,本文我们就来接着介绍这两个组件。目录前言一、Acceptor1、构造方法2、run方法LimitLatchNioChannel二、Poller与PollerEvent2、pollerregisterruneventsprocessKey。

CRUD工程师 2065

深入理解AQS之CountDownLatch

深入理解AQS之CountDownLatch,包括什么事CountDownLatch,使用方法及底层原理

飞奔的小付的博客 851

【雷达仿真 | FMCW TDMA-MIMO毫米波雷达信号处理仿真(可修改为DDMA-MIMO)】

1、FMCW叫做调频连续波,调频连续波有步进调频连续波(SFMCW)、线性调频连续波(LFMCW),以及其他非线性调频连续波。LFMCW有锯齿波和三角波等等;锯齿波有恒定调制周期的锯齿波和非恒定周期的锯齿波。Introduction to mmwave sensing:FMCW radars.pdf和The fundamentals of millimeter wave sensors。2、MIMO是多输入多输出(Multiple input Multiple output),也就是多发多收。

【调皮连续波】雷达技术领域知识博主 1万+

CNN经典论文(一)LeNet

Gradient-Based Learning Applied to Document Recognition(梯度学习在文档识别中的应用) Yann LeCun, Leon Bottou, Yoshua Bengio, and Patrick Haffner 发表时间:December 1998 期刊:Proceedings of the IEEE 影响:世界上第一个卷积神经网络 论文地址:Gradient-Based Learning Applied to Document Recognition

loveling丶的博客 3598

AQS同步组件CountDownLatch详细讲解

1、AQS同步组件CountDownLatch详细讲解。 CountDownLatch:同步辅助类,通过它可以完成类似于阻塞当前线程的功能,换句话说,一个线程或者多个线程一直等待,直到其他线程操作完成,CountDownLatch,给定的计数器,来进行初始化,该计数器的操作是原子操作,同时,只能有一个线程去操作该计数器,调用该类的await()方法的线程会一直处于等待状态,直到其他线程调用cou...

dabiaoge33的博客 466

M2DGR数据集在一些SLAM框架上的配置与运行:ORB-SLAM系列、VINS-Mono、LOAM系列、FAST-LIO系列、hdl_graph_slam

为了说明以上这些SLAM框架的测试与数据集适配,以M2DGR数据集为例进行各自的配置与运行,方便我以后适配自己的数据集,运行的SLAM框架包括:ORB-SLAM2、ORB-SLAM3、VINS-Mono、A-LOAM、LeGO-LOAM、LIO-SAM、LVI-SAM、FAST-LIO2、FAST-LIVO、Faster-LIO、hdl_graph_slam。实验基于Ubuntu20.04,其中ORB、VINS-Mono、和LOAM系列的安装参考我以前的博客,有详细的安装方法,其他的框架在后面会简单介绍一下

zardforever123的博客 1万+

AQS之CountDownLatch

CountDownLatch是java并发包中一个常见的类,本文将从源码的角度来分析CountDownLatch的实现原理,而CountDownLatch是基于AQS的共享锁模式来实现的,所以需要对AQS有一定的了解。

Epoch_Elysian的博客 648

LabVIEW进行MQTT通信及数据解析

该文章介绍了LabVIEW的MQTT通信的开源VI控制,以及如果进行数据的解析,特别是一些需要注意的点

heda3的博客 4106

Oracle EBS 帐套(Ledger/SOB)如何定义会计主体、如何支撑多准则 / 多报告、组织与帐套的绑定关系、以及项目落地时的设计差异。下面从实现逻辑、核心要素、组织模型、多账簿、科目设计、项

本文对比了Oracle EBS R12与SAP S/4HANA在帐套(Ledger)设计上的核心差异。Oracle采用4C架构(科目/币种/日历/准则),帐套作为独立会计主体,主辅账物理隔离;SAP则以公司代码为主体,通过平行分类账在同一凭证中实现多准则核算。关键差异体现在:Oracle强调边界隔离,适合差异大的集团;SAP注重统一视图,适合实时合并需求。实施时需注意:Oracle避免过度建账套,SAP需统筹科目与维度设计。两者分别体现了"盒子"与"滤镜"的设计哲学。

金牌架构师 417

并发编程-16AQS同步组件之CountDownLatch 闭锁

文章目录脑图CountDownLatch闭锁示例Thread#join()CountDownLatchCountDownLatch示例二 await一直等待其他线程执行完CountDownLatch示例三 await指定等待时间小结代码 脑图 CountDownLatch闭锁 Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器...

小工匠 2万+

高通camx进程ExtensionModule::TeardownOverrideSession类型crash问题分析之一:【死锁导致】

摘要:本文分析了一个在相机老化测试中出现的pthread_cond_wait持锁超时导致的ExtensionModule::TeardownOverrideSession崩溃问题。通过crash堆栈和日志分析,发现close阶段存在近1分钟的无响应期。进一步分析trace文件发现存在多线程死锁:ChiFeature2Graph::GenerateSmartErrorCode和ChiFeature2RequestObject::SetCurRequestState两个线程分别持有不同锁并互相等待对方释放。最终

1110

CountDownLatch分析(AQS共享锁)

CountDownLatch 是一个同步工具类,它允许一个线程或多个线程一直等待,知道其他线程的操作执行完毕再执行。从命名可以解读到 countDown 是倒数的意思,类似于我们倒计时的概念。 CountDownLatch提供了两个方法:await()和countDown();countDownLatch 初始化的时候需要传入一个整数,在这个整数倒数到 0 之前,调用了 await 方法的程序都必须要等待,然后通过 countDown 来倒数。 一、Demo public static void m

moneywenxue的博客 715

静态时序分析—门控时钟检查(clock gating check)

clock gating check的条件与类型

m0_61544122的博客 9608

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

CountDownLatch 源码分析

CountDownLatch基于AQS的共享模式实现,内部类Sync继承AbstractQueuedSynchronizer,使用state存储计数器。通过tryAcquireShared判断计数器是否为0(成功返回1,失败返回-1),tryReleaseShared通过循环CAS递减计数器,归零时返回true触发线程唤醒。await()对应acquire操作会阻塞直到计数归零,countDown()对应release操作递减计数。该设计允许多线程在计数器归零时被同时唤醒,而非独占模式下的单个线程唤醒。

赵丙双的博客 220

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

2023 Java面试通关手册:从八股文到体系化表达

在技术岗位的选拔中,基础知识深度始终是衡量候选人的核心标尺。理解JVM内存模型与垃圾回收机制,掌握并发编程中锁升级的底层原理,剖析HashMap在JDK 8中的数据结构演进,这些原理层面的积累不仅是应对面试官连环追问的底气,更是定位线上性能问题的关键技能。从线程池参数调优到Spring事务传播行为,从MySQL索引优化到Redis分布式锁,每个知识点都需要与传统“八股文”形成体系化串联。2023年的面试趋势表明,面试官更倾向于通过场景设计题与源码级追问,探查候选人将知识转化为工程实践的能力。本文以当前Jav

weixin_30412167的博客 610

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

AQS应用--CountDownLatch

AQS应用之CountDownLatch

qq_42029265的博客 528

AQS解密:深入理解 CountDownLatch, Semaphore 和 CyclicBarrier

CountDownLatch是一种同步工具类,它允许一个或多个线程等待其他线程完成一组操作之后再继续执行。CountDownLatch通过一个计数器实现,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减一。当计数器值降至零时,意味着所有的线程都完成了任务,等待的线程就可以恢复执行任务。Semaphore,也称为信号量,是用于控制同时访问某个特定资源的操作数量的同步工具,它管理一系列许可(permits)。

逆流的小鱼 1452

详解AQS五:深入理解共享锁CountDownLatch

此时AQS队列中有11个节点,第一个头部节点是队列初始化的时候创建的虚拟节点,剩余十个节点,前9个节点状态都是SIGNAL(-1),因为它们在抢锁失败后会调用shouldParkAfterFailedAcquire方法,该方法会将当前节点的前置节点修改成SIGNAL(-1),最后一个节点入队后默认状态是0,由于没有后续节点入队了,所以其状态没有变成-1,而是0。接着执行doReleaseShared方法:在N次countDown,一次await模式中,该方法在await方法中的调用什么都没做就结束了循环;

weixin_55010563的博客 1062

9、深入理解AQS之闭锁CountDownLatch

CountDownLatch让一个或多个线程等待其他线程执行完成后再执行。在创建CountDownLatch对象时,必须指定线程数count,每当一个线程执行完成调用countDown()方法,线程数count减1,当count减到0时,await()方法就不再阻塞。

sproutBoy的博客 743

AQS同步组件-CountDownLatch解析和案例

CountDownLatch原理 CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。CountDownLatch可以起到阻塞线程,并保证线程在满足某种特定的情况后继续执行。 ![image.png](https://img-blog.csdnimg.cn/img_convert/da3b3319657cb72af38b50bc6cb

write less , do more 1万+

AQS之CountDownLatch(应用场景)

CountDownLatch又叫计数器,他通过一个共享的计数总量来控制线程锁的获取,当计数器总量大于0时,线程将被阻塞,不能够获取锁,只有当计数器总量为0时,所有被阻塞的线程同时被释放。 应用场景 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。 开始执行前

bool的博客 399

一篇文章彻底搞懂AQS共享工具类CountDownLatch(深度剖析)

围绕CountDownLatch是什么,如何使用、实现原理、核心源码分析、以及和cyclicBarrier区别

大尾巴狼学编程的博客 881
上一篇: 揭下ReentrantLock神秘的面纱
下一篇: Our Collectors
foolishAndStupid
博客等级 码龄12年 53粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值