并发编程:读写锁

news2024/9/20 0:41:15

一、ReentrantReadWriteLock

1.ReentrantReadWriteLock 是什么?

ReentrantReadWriteLock 实现了 ReadWriteLock ,是一个可重入的读写锁,既可以保证多个线程同时读的效率,同时又可以保证有写入操作时的线程安全。

public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable{
}
public interface ReadWriteLock {
    Lock readLock();
    Lock writeLock();
}
  • 一般锁进行并发控制的规则:读读互斥、读写互斥、写写互斥。
  • 读写锁进行并发控制的规则:读读不互斥、读写互斥、写写互斥(只有读读不互斥)。

ReentrantReadWriteLock 其实是两把锁,一把是 WriteLock (写锁),一把是 ReadLock(读锁) 。读锁是共享锁,写锁是独占锁。读锁可以被同时读,可以同时被多个线程持有,而写锁最多只能同时被一个线程持有。

ReentrantLock 一样,ReentrantReadWriteLock 底层也是基于 AQS 实现的。

 

ReentrantReadWriteLock 也支持公平锁和非公平锁,默认使用非公平锁,可以通过构造器来显示的指定。

// 传入一个 boolean 值,true 时为公平锁,false 时为非公平锁
public ReentrantReadWriteLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

2.ReentrantReadWriteLock 适合什么场景?

由于 ReentrantReadWriteLock 既可以保证多个线程同时读的效率,同时又可以保证有写入操作时的线程安全。因此,在读多写少的情况下,使用 ReentrantReadWriteLock 能够明显提升系统性能。

3.共享锁和独占锁有什么区别?

  • 共享锁:一把锁可以被多个线程同时获得。
  • 独占锁:一把锁只能被一个线程获得。

4.线程持有读锁还能获取写锁吗?

  • 在线程持有读锁的情况下,该线程不能取得写锁(因为获取写锁的时候,如果发现当前的读锁被占用,就马上获取失败,不管读锁是不是被当前线程持有)。
  • 在线程持有写锁的情况下,该线程可以继续获取读锁(获取读锁时如果发现写锁被占用,只有写锁没有被当前线程占用的情况才会获取失败)。

5.读锁为什么不能升级为写锁?

写锁可以降级为读锁,但是读锁却不能升级为写锁。这是因为读锁升级为写锁会引起线程的争夺,毕竟写锁属于是独占锁,这样的话,会影响性能。

另外,还可能会有死锁问题发生。举个例子:假设两个线程的读锁都想升级写锁,则需要对方都释放自己锁,而双方都不释放,就会产生死锁。

二、StampedLock

1.StampedLock 是什么?

StampedLock 是 JDK 1.8 引入的性能更好的读写锁,不可重入且不支持条件变量 Condition

不同于一般的 Lock 类,StampedLock 并不是直接实现 LockReadWriteLock接口,而是基于 CLH 锁 独立实现的(AQS 也是基于这玩意)。

public class StampedLock implements java.io.Serializable {
}

StampedLock 提供了三种模式的读写控制模式:读锁、写锁和乐观读。

  • 写锁:独占锁,一把锁只能被一个线程获得。当一个线程获取写锁后,其他请求读锁和写锁的线程必须等待。类似于 ReentrantReadWriteLock 的写锁,不过这里的写锁是不可重入的。
  • 读锁 (悲观读):共享锁,没有线程获取写锁的情况下,多个线程可以同时持有读锁。如果己经有线程持有写锁,则其他线程请求获取该读锁会被阻塞。类似于 ReentrantReadWriteLock 的读锁,不过这里的读锁是不可重入的。
  • 乐观读:允许多个线程获取乐观读以及读锁。同时允许一个写线程获取写锁。

另外,StampedLock 还支持这三种锁在一定条件下进行相互转换。

long tryConvertToWriteLock(long stamp){}
long tryConvertToReadLock(long stamp){}
long tryConvertToOptimisticRead(long stamp){}

StampedLock 在获取锁的时候会返回一个 long 型的数据戳,该数据戳用于稍后的锁释放参数,如果返回的数据戳为 0 则表示锁获取失败。当前线程持有了锁再次获取锁还是会返回一个新的数据戳,这也是StampedLock不可重入的原因。

// 写锁
public long writeLock() {
    long s, next;  // bypass acquireWrite in fully unlocked case only
    return ((((s = state) & ABITS) == 0L &&
             U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
            next : acquireWrite(false, 0L));
}
// 读锁
public long readLock() {
    long s = state, next;  // bypass acquireRead on common uncontended case
    return ((whead == wtail && (s & ABITS) < RFULL &&
             U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
            next : acquireRead(false, 0L));
}
// 乐观读
public long tryOptimisticRead() {
    long s;
    return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
}

2.StampedLock 的性能为什么更好?

相比于传统读写锁多出来的乐观读是StampedLockReadWriteLock 性能更好的关键原因。StampedLock 的乐观读允许一个写线程获取写锁,所以不会导致所有写线程阻塞,也就是当读多写少的时候,写线程有机会获取写锁,减少了线程饥饿的问题,吞吐量大大提高。

3.StampedLock 适合什么场景?

ReentrantReadWriteLock 一样,StampedLock 同样适合读多写少的业务场景,可以作为 ReentrantReadWriteLock的替代品,性能更好。

不过,需要注意的是StampedLock不可重入,不支持条件变量 Condition,对中断操作支持也不友好(使用不当容易导致 CPU 飙升)。如果你需要用到 ReentrantLock 的一些高级性能,就不太建议使用 StampedLock 了。

另外,StampedLock 性能虽好,但使用起来相对比较麻烦,一旦使用不当,就会出现生产问题。

4.StampedLock 的底层原理

StampedLock 不是直接实现 LockReadWriteLock接口,而是基于 CLH 锁 实现的(AQS 也是基于这玩意),CLH 锁是对自旋锁的一种改良,是一种隐式的链表队列。StampedLock 通过 CLH 队列进行线程的管理,通过同步状态值 state 来表示锁的状态和类型。

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

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

相关文章

CDGA|做好数据治理的几个策略,不看后悔

在当今这个数据驱动的时代&#xff0c;数据已成为企业最宝贵的资产之一。然而&#xff0c;随着数据量的爆炸性增长和来源的多样化&#xff0c;如何有效地管理和利用这些数据&#xff0c;即数据治理&#xff0c;成为了企业面临的重要挑战。 良好的数据治理不仅能够提升数据质量&…

中医世家龚洪海博士:用医术和真诚赢得患者的心

医生&#xff0c;可以说是世界上最伟大的人&#xff0c;他们以高超的医疗技术和崇高的职业道德&#xff0c;以患者为先&#xff0c;为患者带来生的奇迹&#xff0c;抚平患者的病痛&#xff0c;是生命忠诚的的捍卫者。明代御医龚廷贤龚氏传人龚洪海博士就是这样一个&#xff0c;…

英国数字化战略下的人工智能时代:挑战与发展机遇

文章目录 前言一、英国数字化转型初探二、数字化转型重点举措1、 供应链2、金融市场3、数字基础设施4、科学研究5、数字技术赋能绿色转型6、数字包容性7、国际合作:重视与发展中国家合作8、完善数字民主建设三、战略启示前言 后疫情时代,英国正面临包括首相更迭频繁导致的内…

AnyGPT:多模态语言模型,任意处理语音、图像和音乐

人工智能咨询培训老师叶梓 转载标明出处 大模型的能力大多局限于文本处理&#xff0c;而现实世界环境本质上是多模态的&#xff0c;涉及视觉、语言、声音和触觉等多种感知渠道。为了使LLM能够更好地模拟人类的多模态感知能力&#xff0c;复旦大学的研究团队提出了AnyGPT&#x…

巴西美客多广告打法,这样开广告有泼天的流量!

听说做巴西美客多本土店不需要开广告就有流量&#xff1f;这是真的吗&#xff1f;相信这对于一直在做欧美市场的卖家来说&#xff0c;简直是不敢相信&#xff0c;What? 有运营巴西美客多本土店铺多年的卖家说&#xff0c;确实是不开广告也能获得不错的流量&#xff0c;过去几…

汽车EDI:montaplast EDI对接

Montaplast 是一家总部位于德国的全球知名汽车零部件供应商&#xff0c;专注于高精度塑料部件的设计、开发和生产。公司成立于1958年&#xff0c;主要为汽车行业提供轻量化、高性能的塑料解决方案。Montaplast 以其在注塑成型技术、表面处理和装配技术方面的专业能力而著称&…

vue3 项目中使用git

一.vue项目创建 二.创建本地仓库并和远程仓库进行绑定 在vue3-project-git 项目文件夹下 初始化一个新的Git仓库&#xff0c;可以看到初始化成功之后就会出现一个.git文件&#xff0c;该文件包含所有必要的 Git 配置和版本控制信息。 创建远程仓库: 打开gitee ,点击右上角 ‘…

电源模块检测方法之功率因数的测量

在设计和维护电源系统时&#xff0c;功率因数是一个不可忽视的参数。那么功率因数是什么呢&#xff1f;怎么测试电源模块的功率因数呢&#xff1f;又该如何提高功率因数呢&#xff1f;让我们一起来探讨吧。 一、功率因数概述 功率因数是指交流电路中有功功率和视在功率的比值&a…

安全产品概述

防火墙 防火墙的核心功能是过滤掉有害的流量&#xff0c;在专用网络和公共网络之间建立保护屏障。防火墙过滤通常基于一系列规则&#xff0c;如 IP 地址、域名、协议、端口号、关键字等&#xff0c;对入站和出站的流量进行过滤。这些规则也称为访问控制列表&#xff08;ACCESS…

假装勤奋,无效努力!看了上热搜的北京十一学校,我更加理解了衡水家长们的无奈——早读(逆天打工人爬取热门微信文章解读)

怀念伟大 引言Python 代码第一篇 看了上热搜的北京十一学校&#xff0c;我更加理解了衡水家长们的无奈第二篇 股市路注定是孤独的结尾 引言 不断尝试新的改变 发现最近把很多时间用在股票上 但是总结复盘却没有多 所以得改 一般是看一个视频讲解 然后一不小心就睡着了 日复一日…

超轻量级、支持插件的 .NET 网络通信框架

目录 前言 项目介绍 项目环境 项目功能 1、功能导图 2、项目文档 项目特点 1、传统 IOCP 与 TouchSocket 的 IOCP 模式 2、数据处理适配器 3、兼容性与适配 项目使用 1、Nuget安装 2、TcpService 3、TcpClient 4、TcpClient 断线重连 项目案例 1、工程师软件工…

elementUI之不会用

form表单注意事项 <template><div class"container"><el-form :model"form" label-width"80px" :rules"RulesName" ref"loginForm"><el-form-item label"姓名" prop"username">…

【阿雄不会写代码】全国职业院校技能大赛GZ036第九套

也不说那么多了&#xff0c;要用到这篇博客&#xff0c;肯定也知道他是干嘛的&#xff0c;给博主点点关注点点赞&#xff01;&#xff01;&#xff01;这样博主才能更新更多免费的教程&#xff0c;不然就直接丢付费专栏里了&#xff0c;需要相关文件请私聊

软件测试外包公司分享:软件产品鉴定测试内容和作用

软件产品鉴定测试是指对软件在不同阶段进行系统性、全面性的检测与评估&#xff0c;确保产品在功能、安全性、性能等方面达到既定标准。这对企业选择、验证及应用软件产品至关重要。 软件产品鉴定测试的内容主要包括以下几项&#xff1a;   1、功能测试&#xff1a;验证软件…

Sumsub 获评 Gartner® “新兴技术:针对在线欺诈预防的 GenAI 安全服务”代表性供应商

AI 为业务增长提供了巨大机遇。但也带来了重大威胁&#xff0c;比如可能会导致企业蒙受数百万美元损失的深度伪造攻击。 近日&#xff0c;全球领先的验证平台 Sumsub 被权威机构 Gartner 列入《新兴技术&#xff1a;针对在线欺诈预防的 GenAI 安全服务》报告的代表性供应商名单…

十二、C语言:内存函数

一、memcpy 1.1 使用 void * memcpy ( void * destination, const void * source, size_t num ); 1.前两个参数类型都是void*&#xff0c;因此可以拷贝任何数据类型&#xff1b; 2.num参数为要拷贝的字节数&#xff1b; int main() {char arr[10] "abcdef";char b…

第三届828 B2B企业节开幕,大腾智能携手华为云共谱数字化新篇章

8月27日&#xff0c;由华为携手上万家伙伴共同发起的第三届828 B2B企业节在贵州正式开幕。 本届企业节推出上万款数智产品&#xff0c;600多个精选解决方案&#xff0c;旨在融通数智供需&#xff0c;加速企业智改数转&#xff0c;助推中国数智产业实力再升级。中共贵州省委副书…

英文外链代发服务靠谱吗?

英文外链代发服务的可靠性因供应商和服务类型而异。外链代发服务的主要目标是提高网站在搜索引擎中的排名&#xff0c;通过增加指向目标网站的链接数量和质量来实现。然而&#xff0c;并不是所有的外链代发服务都是可靠的&#xff0c;很多外链都是只管发&#xff0c;但是发了有…

你真的理解 Kubernetes 中的 requests 和 limits 吗?

你真的理解 Kubernetes 中的 requests 和 limits 吗&#xff1f; https://www.cnblogs.com/kubesphere/p/14632890.htmlhttps://www.cnblogs.com/kubesphere/p/14632890.html在 Kubernetes 集群中部署资源的时候&#xff0c;你是否经常遇到以下情形&#xff1a; 经常在 Kubern…

客户案例 | 使用 BigQuery 和 AutoML 消除电视行业的数据孤岛和分散

在这个客户案例中&#xff0c;我们会介绍一家大众媒体公司如何利用 BigQuery 和 AutoML 消除数据孤岛和分散。通过参考真实的 Google Cloud 案例研究&#xff0c;我们总结了 Google Cloud 的服务和产品如何使客户的业务受益。 Cloud Ace - 谷歌云 | 谷歌云全球战略合作伙伴 | …