ReentrantReadWriteLock锁的使用

通俗易懂读写锁ReentrantReadWriteLock的使用 ReentrantReadWriteLock不知道大家熟悉吗?其实在实际的项目中用的比较少,反正我所在的项目没有用到过。ReentrantReadWriteLock称为读写锁,它提供一个读锁,支持多个线程共享同一把锁。它也提供了一把写锁,是独占锁,和其他读锁或者写锁互斥,表明只有一个线程能持有锁资源。通过两把锁的协同工作,能够最大化的提高读写的性能,特别是读多写少的场景,而往往大部分的场景都是读多写少的。本文主要讲解ReentrantReadWriteLock的使用和应用场景。 阅读详情

1.什么是ReentrantReadWriteLock

    ReentrantReadWriteLock是jdk提供的一个可重入的读写锁,功能与synchronized类似

    什么叫可重入:就是同一个线程可以重复加锁,可以对同一个锁加多次,每次释放的时候回释放一次,直到该线程加锁次数为0,这个线程才释放锁。

    什么叫读写锁: 也就是读锁可以共享,多个线程可以同时拥有读锁,但是写锁却只能只有一个线程拥有,而且获取写锁的时候,其他线程都已经释放了读锁,而且在该线程获取写锁之后,其他线程不能再获取读锁。

    可重入环境举例:递归调用

    ReentrantReadWriteLock并没有继承ReentrantLock,也并没有实现Lock接口!

2.ReentrantReadWriteLock的锁

    ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁,一个写锁

    读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,只要上好相应的锁即可。如果代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;

    如果代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

1、读和读之间不互斥,因为读操作不会有线程安全问题

2、写和写之间互斥,避免一个写操作影响另外一个写操作,引发线程安全问题

3、读和写之间互斥,避免读操作的时候写操作修改了内容,引发线程安全问题

    总结起来就是,多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。

但是:

  1. 先读再写的情况,请先释放读锁,再上写锁,ReentrantReadWriteLock不支持读锁升级为写锁
  2. 先写再读的情况,可以在上写锁的情况,再上读锁,解锁的时候先解读锁再解写锁

3.ReentrantReadWriteLock的使用

(1)创建锁

165150_mG1v_2248830.png

(2)单独读写代码使用

readLock.lock() 表示获得读锁

165208_ixNm_2248830.png

其中,红色框框部分需要注意:

lock 必须在 finally 块中释放。否则,如果受保护的代码将抛出异常,锁就有可能得不到释放,读锁一直未释放的情况下,由于读写锁是互斥的,这个时候如果新的线程想

去写,就无法写入....

同样,writeLock的用法一样:

165229_lhb0_2248830.png

同样也需要在finally中进行释放锁,原因同上

  (3)读写混合情况

    ①先读再写

            务必先释放读锁,再上写锁,否则会造成死锁

    先看下面这段代码:

165255_fMHq_2248830.png

先上了readLock,然后再上writeLock,这时候,会一直死锁,下面的 get write lock 也不会输出

165309_WzU4_2248830.png

修改一下上面的代码,把readLock.unlock()放到writeLock.lock()之前:

165323_V4M6_2248830.png

重新运行代码,就正常输出了:

165347_XRM3_2248830.png

    ②先写再读

    由于ReentrantReadWriteLock支持锁降级,因此这段代码不会造成死锁

165403_SGnF_2248830.png

 

4.ReentrantReadWriteLock获取锁和释放锁的注意点:

1.一个线程获得了多少次锁,就需要解多少次的锁,如果线程获得了两个读锁,但是只解了一次读锁,会造成死锁

2.一个线程未获得该锁,但是执行了解锁,会造成 IllegalMonitorStateException

在代码优化过程中,正好遇到上述问题:

165422_e1wF_2248830.png

一个thread在调用get(Object o)的时候,先去判断时间间隔,是否满足刷新条件,如果满足了条件,则把readLock释放了(reload方法中有writeLock),在reload()执行完毕后, 再去get.

如果不满足刷新条件,则直接return get方法,这个时候,就会出现readLock未解锁的情况,就导致了死锁,其他线程无法更新数据.

如果在catch后面新增 finally:

165439_5Akb_2248830.png

则可以解决死锁问题,但是新的问题来了.....如果进了if判断后的逻辑,readLock先被释放了一遍,最后finally又释放了一遍,这时候,代码运行就会报错(编译不报错),提示java.lang.IllegalMonitorStateException

也就是上面的说的第二点

解决方案:在reload()之后重新上锁,对应finally中的解锁:

165456_WmjO_2248830.png

这样,上锁解锁就一一对应了,既不会造成死锁,也不会出现IllegalMonitorStateException

 

总结一下

ReentrantReadWriteLock

  1. 利用共享模式实现读锁,独占模式实现写锁;
  2. 支持公平和非公平,非公平的情况下可能会出现读锁阻塞写锁的场景;
  3. 写锁阻塞写锁和读锁,读锁阻塞写锁;
  4. 写锁可以降级为读锁,读锁不能升级为写锁,只能先release再lock;
  5. 写锁支持condition条件;
  6. 读写锁都支持超时/中断lock;
  7. 适合读多写少的场景。

 

 

本文参考链接:

http://www.jianshu.com/p/9f98299a17a5 

http://blog.youkuaiyun.com/prestigeding/article/details/53286756

多线程系列(十) -ReadWriteLock用法详解 在上篇文章中,我们讲到ReentrantLock可以保证了只有一个线程能执行加锁的代码。但是有些时候,这种保护显的有点过头,比如下面这个方法,它仅仅就是只读取数据,不修改数据,它实际上允许多个线程同时调用的。 阅读详情

相关推荐

超声波清洗机拆解实录:从电路板到换能器,一文看懂内部构造(附高清图)

本文详细拆解了超声波清洗机的内部构造,从电路板设计到换能器工作原理,揭示了其核心技术。通过高清图片和详细分析,展示了功率放大电路、高频变压器及压电换能器等关键部件,为电子爱好者和维修技术人员提供了实用的故障诊断和元件二次利用指南。

grape的博客 1186

【并发编程学习篇】ReentrantReadWriteLock详解

现实中有这样一种场景对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发)但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读,写写互斥)在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。

一个勤勤恳恳的程序猿 3万+

Kaamel白皮书:Agent-to-Agent(A2A)隐私安全最佳实践

随着AI智能体架构从单体模型演化为多Agent协同系统,A2A协议为智能生态提供了强大的互操作能力。然而,能力越大,责任亦重。若无完备的隐私保护和安全防护体系,A2A将沦为数据泄露、滥权执行的温床。Kaamel作为专注于泛安全方向的Agent基础设施构建者,呼吁业界将“隐私工程”与“安全编排”作为A2A系统设计的核心前提,共建可信Agent生态,守护智能协同时代的数据主权与系统安全。未来,Kaamel计划发布一套“可信Agent协同蓝图”,涵盖:A2A协议适配Agent SDK工具集;

kaamelai的博客 1598

ReentrantReadWriteLock读写锁详解

一、读写锁简介 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。  针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁,描述如下: 线程进入读锁的前提条件: 没有其他线程的写锁..

没有伞的孩子必须努力奔跑!—小林 1293

PotPlayer 史诗级更新!实时字幕生成+实时翻译,看片真的无敌了!

potplayer已经更新实时字幕生成+实时字幕翻译功能

阿虚同学的博客 1万+

基于虚拟阻抗重塑的构网型VSG变流器SISO序阻抗建模与宽频振荡抑制策略分析(面向高比例新能源并网场景)

本文深入探讨了基于虚拟阻抗控制的构网型VSG变流器SISO序阻抗建模技术及其在高比例新能源并网场景中的宽频振荡抑制策略。通过虚拟阻抗重塑,有效改善了变流器的阻抗特性,解决了次/超同步频段的振荡问题,并提供了参数设计、阻抗扫频验证等实用技巧,为新能源并网系统的稳定性提供了可靠解决方案。

weixin_29268385的博客 251

深入理解AQS之ReentrantReadWriteLock详解

文章目录一、读写锁介绍二、ReentrantReadWriteLock的使用2.1 读写锁接口ReadWriteLock2.2 ReentrantReadWriteLock类结构2.3 如何使用读写锁2.4 应用场景2.5 锁降级三、ReentrantReadWriteLock源码分析3.1 ReentrantReadWriteLock结构3.2 读写状态的设计3.3 HoldCounter 计数器3.4 写锁的获取3.5 写锁的释放3.6 读锁的获取3.7 读锁的释放 一、读写锁介绍 现实中有这样一种场景

沮丧的南瓜 864

SAP Joule 在顾问与开发者场景的双擎定位:Joule for Consultants 与 Joule for Developers 全面解读

SAP推出企业级AI助手Joule,分为顾问版(Joule for Consultants)和开发者版(Joule for Developers)两个版本。顾问版聚焦咨询业务,整合SAP知识库和方法论,辅助方案设计、差距分析和实施落地;开发者版嵌入开发工具链,支持代码生成、解释、测试和迁移。两者共享智能底座但面向不同场景:顾问版优化项目交付流程,开发者版提升工程效率。典型案例显示,Joule能有效缩短云转型周期,实现从业务咨询到技术落地的无缝衔接。该产品通过AI代理和知识图谱技术,为企业数字化转型提供端到端

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 355

JAVA中的ReentrantLock和ReentrantReadWriteLock锁简单使用

ReentrantLock的作用和synchronize是一样的,都是实现锁的功能,但是ReentrantLock需要手写代码对锁进行获取和释放(一定要在finally里面释放),要不然就永远死锁了,ReentrantLock也可以用来做线程之间的挂起和通知,synchronize一般是使用object的wait和notify来实现,ReentrantLock使用Condition来实现线程之间的...

madman 7327

QGis二次开发 —— 1.1、ubuntu24.04下搭建QGis3.40.12二次开发环境(附:全部问题解决方法)

QGis二次开发 —— 1.1、ubuntu24.02下搭建QGis3.40.12二次开发环境(附:全部问题解决方法)

252

控制科学与工程(自动化)保研经验【4】——浙大篇

控制科学与工程(自动化)保研经验【4】——浙大篇

Control Everything 1万+

ReentrantReadWriteLock 的使用场景及读锁的必要性

适用于的并发场景,即大部分操作是读取共享资源,而写入操作相对较少。

younuoqianjin的博客 779

Ambari 3.0+BigTop 3.3集群部署实战

Ambari 3.0+BigTop 3.3集群部署

docsz的博客 611

了解ReentrantReadWriteLock锁的使用

了解ReentrantReadWriteLock锁的使用简介读读共享写写互斥读写互斥 简介 1.ReentrantReadWriteLock分为读锁和写锁. 2.读锁也称为共享锁,进行读相关操作,多个线程都可获取该锁. 3.写锁也称为互斥锁,进行写相关操作,同一时刻只允许一个线程获取该锁. 读读共享 示例读读共享代码: /** * TODO * 类ReentrantReadWriteLock的使用:读读共享. * * @author 86182 * @version V1.0 * @since

weixin_43225491的博客 281

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

读锁和写锁(共享锁和排他锁)介绍 以及相关类 ReentrantReadWriteLock 学习总结,使用场景

构造方法public ReentrantReadWriteLock():默认构造方法,非公平锁public ReentrantReadWriteLock(boolean fair):true 为公平锁常用APIpublic ReentrantReadWriteLock.ReadLock readLock():返回读锁public ReentrantReadWriteLock.WriteLock writeLock():返回写锁lock():加锁unlock():解锁。

weixin_44131922的博客 2010

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

并发编程学习笔记(6)----公平锁和ReentrantReadWriteLock使用及原理

(一)公平锁   1、什么是公平锁?   公平锁指的是在某个线程释放锁之后,等待的线程获取锁的策略是以请求获取锁的时间为标准的,即使先请求获取锁的线程先拿到锁。   2、在java中的实现?   在java的并发包中提供了ReentrantLock提供了重入锁并且也提供了公平锁(FairSync)和非公平锁(NonfairSync)。   RenntranLock类的构造方...

xiaoshen66的博客 139

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

java 中 ReentrantReadWriteLock的读锁和写锁的使用

jdk文档中关于ReentrantReadWriteLock类使用的一个很好的例子,以下是具体的介绍:    在使用某些种类的 Collection 时,可以使用 ReentrantReadWriteLock 来提高并发性。通常,在预期 collection很大,读取者线程访问它的次数多于写入者线程,并且 entail 操作的开销高于同步开销时,这很值得一试。例如,以下  是一个使用 Tre

Erica_1230的专栏 2811

ReentrantReadWriteLock 锁转为关键字锁使用

当然分布式并不适用 使用示例 获取锁组 /** * * lockGroupName 锁组名称 * 1000l 该锁组最大包含锁数量 * 5000l 当超过最大锁数量时,被清理锁的持有时间最大值,单位ms */ LockUtils lockUtils = LockUtilsFactory.genLockUtils("lockGroupName", 1000l, 5000l); //加锁,key=关键字 lockUtils.lock(key); try{ }finally { //

qqtbqq的博客 411

Java多线程技术三:锁的使用——使用ReentrantReadWriteLock类

ReentrantLock类具有完全互斥排它的特点,同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务,这样做保证了同时写实例变量的线程安全性,但 效率是非常低下的。在JDK提供了一种读写锁ReentrantReadWriteLock类,可以在同时进行读操作时不需要同步执行,提升运行速度,加快运行效率。这两个类之间没有继承关系。读写锁表示有两个锁,一个是读操作相关的锁,也叫共享锁。另一个是写操作相关的锁,也叫排它锁。

geminigoth的博客 1421

ReentrantReadWriteLock显示锁的使用和分析

使用读/写锁的方法和步骤: 创建一个ReentrantReadWriteLock对象 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 分别获得读取锁和写入锁 private Lock readLock = rwl.readLock(); private Lock writeLock = r

小嗨嗨的博客 461

Java线程之共享锁和排他锁及ReentrantReadWriteLock的使用

共享锁:在锁中,有个叫读锁。读锁也就是共享锁。也就是说多个线程可以同时获取读锁。有了读锁,必然有写锁。写锁的话只能一个线程写,多个线程同时写肯定会有问题,是不是。

weixin_48278764的博客 667

并发编程工具 - ReentrantReadWriteLock读写分离可重入锁、项目上的使用

ReentrantLock本身是一个独占锁,与优化后的synchronized在并发性能上没有太多的优势,所以需要分场景优化。基于读写分离的思想(比如mysql的一主多从,读写分离)那么ReentrantReadWriteLock就诞生了,只有读与写同时发生时需要互斥,读与读之间是安全的。那么就是AQS的独占和共享模式。具体看看其结构: 项目上的使用,数据本身不多,并且修改也是基本不会发生。但是为了防止数据改变之后,还需要重启...

it_lihongmin的博客 508

深入探索Java并发库(JUC)中的ReentrantReadWriteLock

ReentrantReadWriteLock是Java并发库中一种非常实用的读写锁实现,它允许多个线程同时读取共享资源,提高了程序的并发性能。在使用时需要注意正确获取和释放锁,避免死锁等问题;同时根据实际需求选择合适的公平性策略也是非常重要的。通过深入了解和合理使用ReentrantReadWriteLock,我们可以编写出更高效、更安全的并发程序。个人主页。

码到三十五 9715
上一篇: mac安装redis可视化客户端
下一篇: AutoConfig工具使用指南
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值