常用并发工具类(锁和线程间通信工具类)

常用并发工具类总结

JUC 下的常用并发工具类(锁和线程间通信工具类),主要包括 ReentrantLockReentrantReadWriteLockCountDownLatchCyclicBarrierSemaphoreExchanger

ReentrantLock 和 ReentrantReadWriteLock

ReentrantLock 是可重入独占锁,ReentrantReadWriteLock 是可重入读写锁。

ReentrantLock

ReentrantLock 支持公平和非公平锁两种模式,可以通过 new ReentrantLock(boolean fair) 构造方法来指定公平或非公平模式,默认为非公平模式。
注意,公平和非公平模式在这里主要指的是尝试获取锁的线程是否会在排到同步队列末尾之前尝试获取一遍锁

  • 如果在排到队尾之前会尝试获取一边锁,那么就是非公平模式,因为有可能在这一次尝试获取就直接得到了锁,等同于一个插队操作,所以是非公平锁
  • 如果是老老实实排到队尾,那么就是公平模式,因为不会存在插队操作

ReentrantLock 的公平与非公平模式,主要是靠其内部的两个 AQS 子类,FairSyncNonfairSync 来实现的。

RenntrantReadWriteLock

ReentrantReadWriteLock 是读写锁,其主要性质如下:

  • ReentrantReadWriteLock 内部有一个 Sync 对象,用于执行所有的同步机制
    • Sync 类继承了 AQS
    • Sync 类有一个公平锁实现 FairSync,和一个非公平锁实现 NonfairSync
    • Sync 类中 state 的含义为,高 16 位代表获取读锁的次数,低 16 位代表获取写锁的次数
  • 内部有一个 ReadLock 对象(读锁),有一个 WriteLock 对象(写锁)
    • 读锁和写锁实际上都是依赖于 Sync 对象来实现的
    • 基于 Sync 对象对于 state 的定义,读锁和写锁的获取次数上限都为 65535 (2^16-1
    • 读锁的加锁操作本质上是对 state 的高 16 位进行 +1 操作,释放锁本质上是对 state 的高 16 位进行 -1 操作
    • 写锁的加锁操作本质上是对 state 的低 16 位进行 +1 操作,释放锁本之上是对 state 的低 16 位进行 -1 操作
  • 操作顺序与互斥关系
    • 读读不互斥
    • 写写互斥
    • 读写互斥
    • 写读互斥
  • 读锁和写锁均可重入
  • 读锁不能升级为写锁(即持有读锁时去获取写锁)
    • 如果使用 writeLock().lock() 获取写锁会发生死锁
    • 如果使用 writeLock().tryLock(long timeout, Timeunit unit) 会在超时后返回
  • 写锁可以降级为读锁(即持有写锁时去获取读锁)
  • 读锁和写锁的加锁和释放锁的逻辑必须成对出现

Semaphore

Semaphore信号量的意思,主要用于限定临界资源同时能被多少个线程访问。主要特性:

  • 内部有一个 Sync 类继承了 AQS,是 AQS 共享模式的一种具体实现
  • Sync 类有一个公平锁实现 FairSync,和一个非公平锁实现 NonfairSync,由构造函数 public Semaphore(int permits, boolean fair) 来指定
    • 公平锁实现,当前线程获取不到许可时,将会进入队列等待
    • 非公平锁实现,当前线程将会一直(自旋)尝试获取许可
  • Sync 类中 state 的含义为 public Semaphore(int permits)permits 的数值(许可的数量
  • Sync 类的获取许可操作本质上是对 state-1 操作,释放许可操作本之上是对 state+1 操作

Exchanger

Exchanger交换器的意思,主要用于两个线程之间的数据交换。
注意在多个线程同时使用一个 Exchanger 对象进行数据交换的时候,交换结果可能是未知的。所以 Exchanger 适用于成对线程之间的数据通信。

CyclicBarrier

CyclicBarrier循环栅栏的意思,主要用于帮助多个线程同时达到某个等待点后再把这些线程唤醒。主要特性:

  • 主要的构造函数为 public CyclicBarrier(int parties)public CyclicBarrier(int parties, Runnable barrierAction)
    • parties 代表的是参与协作的线程数量
    • barrierAction 代表的是协作线程的数量等于 parties 时,将会执行的动作
  • CyclicBarrier 有一把内置的 ReentrantLock 锁,和由这把锁创建出来的一个 Condition 对象
  • 当调用 await() 方法时,首先会尝试获取锁,获取成功后当前需要等待的剩余协作线程数量 -1
    • 如果此时需要等待的剩余协作线程数量不为 0,即代表参与协作的线程数量还没有到达初始设定的数量,则调用 Condition 对象的 await() 方法,将当前线程阻塞在 Condition 对象的条件队列中
    • 如果此时需要等待的协作线程数量为 0,即代表参与协作的线程数量已经到达了初始设定的数量,则执行打开栅栏动作(调用 nextGeneration() 方法),(调用 Condition 对象的 singalAll() 方法)唤醒所有等待在 Condition 对象上的线程,唤醒完成后,重置栅栏到初始状态
  • 当调用 reset() 方法时,之前调用了 await() 方法的所有线程将会被唤醒,并抛出异常
  • 当某个线程调用了 await() 方法后被中断,那么 CyclicBarrier 会被设置成一个中断状态,此时需要调用 reset() 方法把 CyclicBarrier 对象重置成初始状态

总的来说 ,CyclicBarrier 是通过 AQS 的条件等待机制(ConditionObject)来实现的

CountDownLatch

CountDownLatch计数门闩的意思,主要用于在一组执行线程都到达某个等待点之后,再唤醒等待在这个门闩上的所有线程一个同步工具。

  • 内部有一个 Sync 类继承了 AQS,是 AQS 共享模式的一种具体实现
  • Sync 类中 state 的含义为 public CountDownLatch(int count)count 的数值(需要打开门闩的次数
  • 调用 countDown() 方法后(相当于尝试释放共享锁),将会使用 CAS + 自旋将 state 变量值 -1
  • 调用 await() 方法后(相当于尝试获取共享锁),首先会判断当前的 state 是否等于 0
    • 如果等于 0,则获取成功,将会立马返回
    • 如果不等于 0,则获取失败,当前线程将会被封装为共享节点放入到 AQS 同步队列中,并阻塞

CyclicBarrier 和 CountDownLatch 的异同

相同点:

  • 都是 JUC 包下的同步工具类
  • 都是 AQS 的应用实例
  • 都可以在指定数目个线程到达某个等待点后,执行一些动作

不同点:

  • 实现目标不同:
    • CyclicBarrier 是帮助多个协作线程最终都到达某个等待点后,再同时唤醒这些协作线程本身
    • CountDownLatch 是在多个执行线程最终都到达某个等待点后,再同时唤醒所有等待线程
  • 调用方式不同:
    • CyclicBarrier 调用 await() 方法后,如果此时的 count 值不为 0,那么将会阻塞自身,所以不能在同一时间连续调用
    • CountDownLatch 在调用 countDown() 方法后,不会阻塞自身,在同一时间可以连续调用
  • 阻塞、修改计数计数和通知的对象不一样:
    • CyclicBarrier 阻塞、修改计数和通知的对象都是执行 await() 方法的线程
    • CountDownLatch 阻塞和通知的是调用 await() 方法的线程,修改计数的对象是执行 countDown() 方法的线程
  • 实现方式不同:
    • CyclicBarrier 是基于 AQS 的条件等待机制来实现的
    • CountDownLatch 内部有一个 Sync 类直接继承了 AQS,是 AQS 共享机制的一种实现
  • 状态是否可重置:
    • CyclicBarrier 可以在到达计数条件后重置自身状态,可以重复使用;也可以主动调用 reset() 方法来重置自身状态
    • CountDownLatch 不能重置自身状态,不能重复使用
  • 计数条件到达后是否可以执行操作:
    • CyclicBarrier 可以调用 public CyclicBarrier(int parties, Runnable barrierAction) 中传入计数条件到达后的操作。在计数条件到达之后,将会调用 barrierActionrun() 方法执行一些特殊操作
    • CountDownLatch 不能设置计数条件到达后的执行操作

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

of方法:给集合一次性添加多个元素

of()方法只是Map,List,Set这三个接口的静态方法,其父类接口和子类实现并没有这类方法,比如 HashSet,ArrayList返回的集合是不可变的,再次添加会报错Set与Map集合不可以存储重复的元素,否则会报错…

数控车椭圆编程实例带图_数控车床编程教程,图文实例详解

一、数控车编程特点(1) 可以采用绝对值编程(用X、Z表示)、增量值编程(用U、W表示)或者二者混合编程。(2) 直径方向(X方向) 系统默认为直径编程,也可以采用半径编程,但必须更改系统设定。(3) X向的脉冲当量应取Z向的一半。(4)采用固定循环,简化…

常用并发工具类(并发集合类)

文章目录概述BlockingQueueArrayBlockingQueue数据存储相关属性阻塞特性相关属性主要方法LinkedBlockingQueueLinkedBlockingQueue 主要属性LinkedBlockingQueue 设计思想ConcurrentLinkedQueuePriorityBlockingQueuePriorityBlockingQueue 主要属性PriorityBlockingQueue 设计…

参考文献起止页码怎么写_毕业论文文献综述不会写?快来看看这篇文章(附含通用模板)...

文献综述是对所研究主题的现状进行客观的叙述和评论、寻求新的研究突破点。一个资料全面、研究深入的综述不仅可以帮助作者确立毕业论文的选题,还可以为论文的深入研究提供有力的支撑。本文分享一份"毕业论文文献综述万能模板",以供参考。一、文献综述的基…

常用并发工具类(线程池)

文章目录概述ThreadPoolExecutorThreadPoolExecutor 的主要属性Worker 主要属性线程池的状态线程池的状态流转线程池提交任务的执行流程线程数量的设置线程池的种类FixedThreadPoolCachedThreadPoolSingleThreadExecutorScheduledThreadPoolExecutorSingleThreadScheduledExecu…

【Java 8 新特性】Java Stream.of()用法示例

本页将介绍Java Stream.of方法示例。Stream.of用于为给定元素创建顺序流。我们可以传递单个元素或多个元素。 查看javadoc中Stream.of方法声明。 static <T> Stream<T> of(T t) 参数&#xff1a;传递单个元素。 返回&#xff1a;该方法返回一个包含一个元素的流。…

Java 类加载机制

文章目录概述类的生命周期类加载的时机类加载的主要 5 个阶段加载验证准备准备阶段初始值的含义解析符号引用直接引用解析阶段的理解静态绑定与动态绑定初始化类加载器类加载器与类之间的关系类加载器的种类双亲委派机制双亲委派机制设计目的破坏双亲委派机制破坏双亲委派机制的…

Java –什么是瞬态字段?

在Java中&#xff0c; transient字段在序列化过程中被排除。 简而言之&#xff0c;当我们将对象保存到文件中&#xff08;序列化&#xff09;时&#xff0c;所有transient字段都将被忽略。 1. POJO 瞬态 复查以下Person类&#xff1b; 薪水领域是transient 。 public class …

JVM 内存模型与内存分配方式

文章目录JVM 内存模型概述基于分代收集理论设计的垃圾收集器所管理的堆结构方法区的演变内存分配划分内存的方法划分内存时如何解决并发问题对象栈上分配基于分代收集理论的垃圾收集器管理下的内存分配规则对象优先分配在 Eden 区大对象直接进入老年代长期存活的对象将逐步进入…

image pil 图像保存_如何利用python中的PIL库做图像处理?

自从这个世界上出现了Python编程&#xff0c;一切都好像有了新的思路与进展&#xff0c;比如人工智能&#xff0c;还有我们常用的PS&#xff0c;你可知道Python也可以做图像处理&#xff0c;用的就是PIL库&#xff0c;还没有用过的&#xff0c;还没有发现的&#xff0c;还没有实…

GSON详解

GSON GSON弥补了JSON的许多不足的地方&#xff0c;在实际应用中更加适用于Java开发。在这里&#xff0c;我们主要讲解的是利用GSON来操作java对象和json数据之间的相互转换&#xff0c;包括了常见的对象序列化和反序列化的知识。 一、前言 因为json有2种类型&#xff1a; 一…

机器人 瓷砖墙面清洗_墙壁清洁机器人解析

1第一章绪论1.1课题的背景、目的及意义[1]壁面清洗爬壁机器人属于移动式服务机器人的一种&#xff0c;可在垂直壁面或顶部移动&#xff0c;完成其外表面的清洗作业。在工业机器人问世30多年后的今天&#xff0c;它已被世人看作是一种生产工具&#xff0c;在制造、装配及最近在服…

内存回收算法与 Hot Spot 算法实现细节

文章目录内存回收算法概述对象存活判定算法引用计数算法可达性分析算法垃圾收集算法分代收集理论标记-清除算法标记-复制算法半区复制算法Appel 式复制算法Appel 式复制算法的逃生门设计标记-整理算法HotSpot 虚拟机实现细节GC Root 枚举Hot Spot 实现 GC Root 枚举安全点与安全…

link st 量产工具_ST-Link资料03_ST-Link固件升级、驱动下载安装方法

说明&#xff1a;本文原创作者『strongerHuang』本文首发于微信公众号『嵌入式专栏』&#xff0c;同时也更新在我的个人网站&#xff1a;EmbeddedDevelop一、写在前面前两篇文章讲述的都是关于ST-Link的一些理论知识&#xff0c;建议初学者看看&#xff1a;ST-Link资料01_ST-Li…

Java 主流垃圾收集器

文章目录垃圾收集器概述Serial 与 Serial Old 垃圾收集器Serial 与 Serial Old 垃圾收集器总结ParNew 垃圾收集器Parallel Scavenge 垃圾收集器Parallel Scavenge 的吞吐量控制参数Parallel Scavenge 的自适应调节策略Parallel Scavenge 垃圾收集器总结ParNew 和 Parallel Scav…

SSM 框架整合 spring 发送邮件功能实现!

基于SSM的 spring 发送邮件的实现 由于考虑到项目中需要&#xff0c;如果程序出现异常或其它问题&#xff0c;可以发送邮件来及时提醒后台维护人员处>理。所以目前考虑使用JavaMail来实现邮件发送&#xff01;如下&#xff0c;是我整理的一些内容&#xff0c;做个笔记记录下…

Java 故障处理与性能监控工具

文章目录概述基础工具jpsjstatjinfojmapjhatjstack高级工具VisualVMVisualVM 的主要功能ArthasGC Easy概述 在使用 Java 语言进行开发的过程中&#xff0c;我们很可能会遇到各种程序问题。 比如&#xff0c;可能会遇见程序突然就静止不动了&#xff0c;但是程序进程依然显示在…

SSM整合框架实现发送邮件功能

SSM整合框架实现发送邮件功能 1.导入发送邮件的依赖 <!-- 发送邮件jar包--><!--spring支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.0.RELE…

ap接口 php_2018年小米高级 PHP 工程师面试题(模拟考试卷)

点击蓝字关注我们&#xff01;每天获取最新的编程小知识&#xff01;源 / php中文网 源 / www.php.cn在面试之前多看看有关公司的面试资料&#xff0c;对之后的面试会很有帮助。今天就给大家带来2018年小米高级 PHP 工程师面试题(模拟考试卷)&#xff0c;有着一定的参考价…

composer 设置版本号_Composer依赖管理 – PHP的利器

别再到处搜PHP类扩展包了&#xff0c;对于现代语言而言&#xff0c;包管理器基本上是标配。Java 有 Maven&#xff0c;Python 有 pip&#xff0c;Ruby 有 gem&#xff0c;Nodejs 有 npm。PHP 的则是 PEAR&#xff0c;不过 PEAR 坑不少&#xff1a;依赖处理容易出问题配置非常复…