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

CountDownLatch和CyclicBarrier源码详解

 其他系列文章导航

Java基础合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

  • 其他系列文章目录
  • 文章目录
  • 前言


前言

我现在有个场景:现在我有50个任务,这50个任务在完成之后,才能执行下一个函数,要是你,你怎么设计?

可以用JDK给我们提供的线程工具类,CountDownLatch和CyclicBarrier都可以完成这个需求。


一、CountDownLatch和CyclicBarrier

CountDownLatch允许一个或多个线程直等待,直到这些线程完成它们的操作。

而CyclicBarrier不一样,它往往是当线程到达某状态后,暂停下来等待其他线程等到所有线程均到达以后,才继续执行。

可以发现这两者的等待主体是不一样的。

CountDownLatch调用await()通常是主线程/调用线程,而CyclicBarrier调用await()是在任务线程调用的。

所以,CyclicBarrier中的阻塞的是任务的线程,而主线程是不受影响的。


二、CountDownLatch源码分析

CountDownLatch也是基于AQS实现的,它的实现机制很简单。

Java 中 AQS(AbstractQueuedSynchronizer)的 state 一般有以下值:

  1. 0:表示当前没有任何线程占有锁或者资源。

  2. 1:表示当前有一个线程占有锁或者资源。

  3. 大于等于 2:表示当前有多个线程占有锁或者资源,即存在竞争状态。

  4. 负数:表示当前有等待获取锁或者资源的线程,这些线程处于阻塞状态。

  5. 特殊值:AQS 实现类可以根据自己的需求自定义特殊的 state 值,例如 ReentrantLock 就使用了一个表示重入次数的 state 值。

当我们在构建CountDownLatch对象时,传入的值其实就会赋值给AQS的关键变量state。

执行countDown方法时,其实就是利用CAS将state -1。

执行await方法时,其实就是判断state是否为0,不为0则加入到队列中,将该线程66阻塞掉(除了头结点)。

因为头节点会一直自旋等待state为0,当state为0时,头节点把剩余的在队列中阻塞的节点也一并唤醒。


三、CyclicBarrier源码分析

回到CyclicBarrier代码也不难,重点也就是await方法。

从源码不难发现的是,它没有像CountDownLatch和ReentrantLock使用AQS的state变量,而CyclicBarrier是直接借助ReentrantLock加上Condition 等待唤醒的功能进而实现的。

在构建CyclicBarrier时,传入的值会赋值给CyclicBarrier内部维护count变量,也会赋值给parties变量(这是可以复用的关键)。

每次调用await时,会将count -1,操作count值是直接使用ReentrantLock来保证线程安全性。

如果count不为0,则添加则condition队列中。

如果count等于0时,则把节点从condition队列添加至AQS的队列中进行全部唤醒并且将parties的值重新赋值为count的值(实现复用)。


四、总结

CountDownlatch基于AQS实现,会将构造CountDownLatch的入参传递至statecountDown()就是在利用CAS将state减1,await)实际就是让头节点一直在等待state为0时,释放所有等待的线程。

CyclicBarrier则利用ReentrantLock和Condition,自身维护了count和parties变量。每次调用await将count-1,并将线程加入到condition队列上。等到count为0时,则将condition队列的节点移交至AQS队列,并全部释放。



http://www.kler.cn/a/146868.html

相关文章:

  • 计算机网络-MSTP基础实验一(单域多实例)
  • 笔记01----Transformer高效语义分割解码器模块DEPICT(即插即用)
  • EEG+EMG学习系列 (1) :一个基于小波的自动睡眠评分模型
  • Liunx-Ubuntu22.04.1系统下配置Anaconda+pycharm+pytorch-gpu环境配置
  • 【快速入门】前端御三家:HTML、CSS和JS
  • vulhub之log4j
  • 计算机毕业设计 基于SpringBoot的无人智慧超市管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解+答疑
  • android基于UDP实现聊天小功能
  • 计算机毕业设计|基于SpringBoot+MyBatis框架的仿天猫商城购物系统设计与实现
  • 第1章 爬虫基础
  • B树与B+树的对比
  • 树的序列化与反序列化
  • 自建CA实战之 《0x01 Nginx 配置 https单向认证》
  • C#线程 ConcurrentQueue安全队列介绍
  • Redis-性能优化
  • 视频号小店是什么?新手入驻需要什么条件?一篇详解!
  • tp8 使用rabbitMQ(1)简单队列
  • 企业联系方式真的那么难获取吗?
  • 力扣6:N字形变化
  • 【C语法学习】28 - 字符测试函数
  • 语音识别学习笔记
  • 【云备份】数据管理模块
  • 【MyBatisPlus】通俗易懂 快速入门 详细教程
  • 代码随想录算法训练营第五十七天|739. 每日温度、496.下一个更大元素 I
  • java学习part13Object类和常用方法
  • C#中的事件(委托的发布和订阅、事件的发布和订阅、EventHandler类、Windows事件)