【JUC-7】ReentrantLock (可重入锁)基础

ReentrantLock (可重入锁)

ReentrantLock实现了Lock接口, 内部通过继承AQS, 实现了一个同步器. 可以通过同步器来创建Condition条件变量, 可以用作容器, 存放不同条件的等待线程.

说明ReentrantLock与AQS的关系 类图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kNl3dfGd-1688483369185)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1688306634769.png)]

相对于synchronized, 都支持可重入. 它还具备如下特点:

  1. 可重入性:与synchronized关键字一样,ReentrantLock是可重入的,即同一个线程可以多次获取同一个锁而不会造成死锁。
  2. 公平性选择:ReentrantLock提供了公平锁和非公平锁的选择。公平锁会按照线程的请求顺序来获取锁,而非公平锁则不保证公平性,可能导致某些线程长时间等待。
  3. 锁获取和释放:使用ReentrantLock可以通过lock()方法获取锁,并通过unlock()方法释放锁。需要注意的是,获取锁后一定要在合适的地方释放锁,通常使用finally块来确保锁的释放。
  4. 条件变量:ReentrantLock提供了条件变量(Condition)的支持,通过newCondition()方法创建条件变量。条件变量可以让线程在特定的条件下等待或被唤醒,常与锁配合使用。
  5. 中断响应:ReentrantLock支持对线程的中断响应。在等待锁的过程中,可以通过调用lockInterruptibly()方法使线程对中断作出响应。
  6. 锁的可见性:与synchronized关键字一样,ReentrantLock同样保证了锁的可见性,即当一个线程释放锁时,对应的变量修改将对其他线程可见。

lockInterruptibly() :

是一个可以被打断的获取锁操作, 相当于是支持interrupt()方法的lock()方法. 普通的lock()方法如果被其他线程阻塞, 是无法通过interrupt()方法打断的, lockInterruptibly()方法, 是在加锁的时候如果被阻塞, 允许被打断.

Condition :

Condition是条件变量对象, 相当于是一个存放等待线程的容器, 比如在线程池中, 就会使用到Condition, 来存放不同的工作线程.

阻塞方法: await() 相当于 object对象的wait()

唤醒方法: signal() 相当于 object对象的 notify()

使用方法: 使用condition之前, 必须调用ReentrantLock对象的lock方法, 之后调用condition.await() 方法, 就把该线程加到condition对象中等待了, 后续执行signal() 方法, 就会从condition容器中随机唤醒一个线程, 继续执行

线程池是如何使用Condition的?

线程池没有直接使用Condition, 而是通过缓冲队列来使用Condition, 让线程没有任务执行时, 进入wait状态, 当有任务时, 会被唤醒执行任务.

例如, 在ArrayBlockingQueue队列中, 维护了两个condition, 一个是notEmpty, 当线程池调用队列的take方法获取任务执行的时候, 队列会判断当前队列中是否存在等待中的任务, 如果存在, 则取出执行, 如果没有, 则进入notEmpty Condition等待. 源码如下

线程池从队列获取任务, 队列中没任务, 则线程进入notEmpty等待

    public E take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {// 队列中任务数量为0while (count == 0)// 进入notEmpty等待notEmpty.await();// 如果不为0 , 取出执行任务return dequeue();} finally {lock.unlock();}}

线程往队列中加入任务时, 如果队列满了, 则进入notFull中等待

    public void put(E e) throws InterruptedException {checkNotNull(e);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (count == items.length)notFull.await();enqueue(e);} finally {lock.unlock();}}
  1. notEmpty条件:用于控制任务队列中是否有任务可执行的条件。当任务队列为空时,线程池的工作线程会等待在notEmpty条件上,直到有新的任务被提交到任务队列中,此时会调用notEmpty.signal()方法来通知等待的工作线程继续执行任务。
  2. notFull条件:用于控制任务队列中是否还有空间可以接受新的任务的条件。当任务队列满时,如果线程池的最大线程数未达到限制,新提交的任务会直接创建新的工作线程来执行。当任务队列中有空闲位置时,线程池的工作线程会等待在notFull条件上,直到有新的任务被提交或者有工作线程被空闲释放,此时会调用notFull.signal()方法来通知等待的工作线程继续执行任务。

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

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

相关文章

对弈人工智能!myCobot 280开源六轴机械臂Connect 4 四子棋对弈

Connect 4 myCobot280 Introduction Hi,guys.今天我们来介绍一下人工智能下棋,我们将用机械臂来作为对手跟你进行下棋。 人工智能下棋的研究可以追溯到20世纪50年代。当时,计算机科学家开始探索如何编写程序,使计算机能够下象棋。其中最著…

Linux 解决root用户被限制连接服务器

Linux 解决root用户被限制连接服务器 1. 问题描述2. 解决问题2.1 方式一(忘记root密码的情况)2.2 方式二(知道root密码的情况) 3. 其他 1. 问题描述 使用 root 用户不能链接服务器,密码对,就是连接不上&am…

VBA之正则表达式(42)-- 快速提取名称

实例需求:A列为待处理数据,现需要从中提取商品名、通用名、胰岛素笔相关信息,保存到B列至D列,需要注意如下几点: 胰岛素笔(E列)数据只存在于每组产品的第一行记录中,例如第2行数据中…

Apikit 自学日记:保存、使用测试用例

API测试用例是SaaS版本企业版才能使用的功能,免费版用户可通过付费升级后使用。 API管理应用中的测试用例管理涉及到两个场景:单接口测试用例管理 和 多接口测试用例批量测试。 一、单接口测试用例管理 功能入口:API管理应用 / 选中某个项目…

vscode copilot长时间没反应

检测问题 首先看一下OUPUT插件信息有什么异常 如果没有异常,但是也没输出 那是请求没有相应的原因 可以在vscode里设置一下代理 参考:https://github.com/orgs/community/discussions/29127

ArcPy学习心得系列(5)遥感数据中值滤波与均值滤波实现方法(不计入NoDATA)

在数据处理与应用的过程中,我们难免会遇到一些低质量的遥感数据,低质量遥感数据一般是由于天气因素导致的,在云量较多时,卫星传感器所采集到的地面信息被云层所遮挡,导致遥感图像成像过程中产生了较多噪声,对遥感数据的精确度造成了一定影响,如果不解决这些数据中的噪声…

【UE5 Cesium】05-Cesium for Unreal 在子关卡中添加Actor

上一篇:【UE5 Cesium】04-Cesium for Unreal 将不同地区的倾斜摄影作为不同子关卡 步骤 首先将关卡切换到“DenverRooftop” 添加一个“立方体” 将关卡切换到“Globe” 然后再向场景中添加一个“椎体” 此时如果我们将关卡切换到“Boston”,只能看到“…

我的毕业故事

前言 2023年6月25日,在拿到双证(毕业证书/学士学位证书)之后,我正式毕业,结束了本科学习阶段。 由于毕业设计中了盲审,因此在大致顺利的过程中平添了不少故事,这里就对近两个月做一个回顾。 盲审 首先解释一下什么…

c++高性能264/265实时h5流媒体服务器前后端整体解决方案

c高性能264/265实时h5流媒体服务器前后端整体解决方案 1.效果展示 下图展示了前端播放效果。 播放1路264视频流,4路265视频流 CPU占用率10%(测试机器上运行着c服务端和其他工具程序) GPU0占用率17% 1.1 作者测试机器配置 处理器 11th Gen Intel Core™ i7-118…

AI 语音 - 人物音色训练

前情提要 2023-07-02 周日 杭州 阴晴不定 AI 入门三大项,AI 绘画基础学习,AI 语音合成,AI 智能对话训练,进入 AI 语音合成阶段了,搓搓小手很激动的,对于一个五音不全的我来说,这个简直了(摆脱…

Spring容器获取Bean的9种方式 | 京东云技术团队

1 前言 随着SpringBoot的普及,Spring的使用也越来越广,在某些场景下,我们无法通过注解或配置的形式直接获取到某个Bean。比如,在某一些工具类、设计模式实现中需要使用到Spring容器管理的Bean,此时就需要直接获取到对…

4.设计模式之后七种模式后11种模式命令访问者迭代器发布订阅中介者忘备录解释器状态策略职责链和空模式

1.命令(command)模式 不知道命令接收者(对象)是谁,支持撤销 (接受者 间接调用执行 的具体行为) 命令调用者和接收者解耦 //只要实现命令接口即可 (就是客户端给个命令,然后命令类传给接收类执行) 优点和缺点 容易撤销操作 命令队列可以多线程操作 增加过多的命令类 空命令也是一…