有没有比读写锁更快的锁

在之前的文章中,我们介绍了读写锁,学习完之后你应该已经知道了读写锁允许多个线程同时访问共享变量,适用于读多写少的场景。那么在读多写少的场景中还有没有更快的技术方案呢?还真有,在Java1.8这个版本里提供了一种叫StampedLock的锁,它的性能就比读写锁还要好。
下面我们介就来介绍一下StampedLock的使用方法、内部工作原理以及在使用过程中需要注意的事项。

StampedLock支持的三种模式

我们先来看看StampedLock在使用什么,和上篇文章中的ReadWriteLock所有哪些区别。
ReadWriteLock支持两种模式,一种是读锁,一种是写锁,而StampedLock支持三种模式,分别是写锁、悲观锁锁、乐观读,其中写锁、悲观读锁的语义和ReadWriteLock的写锁、读锁的语义非常类似。允许多个线程同时获取悲观读锁,但是只允许一个线程获取写锁,写锁和悲观读锁都是互斥的,然而不同的是里面的写锁和悲观读锁加锁成功之后,都会返回一个stamp。然后解锁的时候需要传入这个stamp。相关的实例代码如下。

final StampedLock sl = new StampedLock();//获取/释放悲观读锁示意代码
long stamp = sl.reaLock();
try{//省略业务代码
} finally {sl.unlockRead(stamp);
}//获取/释放写锁示意代码
long stamp = sl.writeLock();
try{//省略相关业务代码
} finally {sl.unlockWrite(stamp);
}

StampedLock 的性能之所以比ReadWriteLock还要好,关键是StampedLock支持乐观读的方式。ReadWriteLock支持多个线程同时读,但是当多个线程同时读的时候,所有的写操作也会被阻塞。而StampedLock提供的乐观读是允许一个线程获取写锁的,也就是说不是所有写操作都被阻塞的。
注意,这里我们用的是"乐观读"这个词,而不是乐观读锁,是要提醒你,乐观读操作是无锁的,所以相比较ReadWriteLock的读锁,乐观读的性能更好一点。文中下面这段代码是出自于Java SDK官方示例,并略作修改。在distanceFromRrigin()这个方法中,首先通过调用tryOptimisticRead获得了一个stamp。这里的tryOptimisticRead就是我们前面提到的乐观读。之后将共享变量X和Y读入方法的局部变量中。不过需要注意的是,由于tryOptimisticRead是无锁的,所以共享变量X和Y读入方法局部变量时,X和Y有可能被其他线程修改了,因此最后读完之后还需要再次验证一下是否存在写操作,这个操作是通过调用validate (stamp)来实现的。

class Point {private int x,y;final StampedLock sl = new StampedLock();//计算到原点的距离int distanceFromOrigin(){//乐观读long stamp = sl.tryOptimisticRead();//读入局部变量//读的过程中数据可能被修改int curX = x,curY = y;//判断执行读操作期间,是否存在写操作//如果存在,返回falseif(!sl.validate(stamp)){//升级为悲观锁stamp = sl.readLock();try{curX = x;curY = y;} finally {sl.unLockRead(stamp);}}return Math.sqrt(curX * curX + curY * curY);}
}

在上面这个代码示例中,如果执行乐观读操作期间存在写操作,会把乐观读升级为悲观读锁。这个做法挺合理的,否则你就需要在一个循环里反复执行乐观读,直到执行乐观读操作期间没有写操作,只有这样才能保证X和Y的正确性和一致性。而循环读会浪费大量的CPU。升级为悲观读锁代码简练且不易出错,建议你在具体实践的时候也采用这样的方法。

进一步理解乐观读

如果你曾经用过数据库的乐观锁,你可能会发现StampLock的乐观读和数据库的乐观读锁有异曲同工之妙。的确是这样的,就我个人而言,我是先接触数据库的乐观锁,然后再接触的StampLock,我就觉得我前期数据库里的乐观锁的学习,对于后面的理解StampLock的乐观读有很大的帮助,所以这里有必要再介绍一下数据库里的乐观锁。
还记得我第一次使用数据库乐观锁的场景是这样的,在ERP的生产模块里,会有多个人通过ERP系统提供的UI同时修改同一条生产订单,那如何保证生产订单数据是并发安全的呢?我采用的方案就是乐观锁。
乐观锁的实现很简单,在生产订单的表product_doc里面增加一个数字型的版本号字段version,每次更新product_doc这个表的时候,都将version字段加1。生产订单的UI在展示的时候需要查询数据库。此时将这个version字段和其他业务字段一起返回给生产订单UI。假设用户查询的生产订单的ID=777,那么SQL语句类似于下面这样。

select id,....,version
from product_doc
where id = 777

用户在生产订单UI执行保存操作时候,后台利用下面的SQL语句更新生产订单,此时我们假设该条生产订单的version等于9。

update product_doc
set version=version+1
where id=777 and versoin=9

如果这条语SQL语句成执行成功,并且返回的条数等于1,那么说明从生产订单UI执行查询操作到执行保存操作期间没有其他人修改过这条数据。因为如果这期间其他人修改过这条数据,那么版本号一定会大于9。
你会发现数据库里的乐观锁查询的时候需要把version字段查出来,更新的时候要利用version字段做校验,这个version字段就类似于StampLock里面的stamp,这样对比着看,你相信你会更容易理解StampLock里面乐观读的用法。

StampLock使用注意事项

对于读多写少的场景StampLock性能很好,简单的应用场景基本上可以替代ReadWriteLock,但是StampLock的功能仅仅是ReadWriteLock的子集,在使用的时候还是有几个需地方需要注意一下。
StampLock在命名上并没有增加Reentrant,想必你已经猜到了,StampLock应该是不可重入的,事实上的确是这样的,StampLock不支持重入,这个是在使用中必须要注意的。
另外StampLock的悲观读锁、写锁都不支持条件变量,这个你也需要注意。
还有一点需要特别注意,那就是如果线程阻塞在StampLock的readLock()上时,此时调用该阻塞线程的interrupt()方法会导致CPU飙升。
所以使用StampLock一定不要调用中断操作,如果需要支持中断功能,一定使用可中断的悲观读锁readLockInterruptibly()和写锁writeLockInterruptibly(),这个规则一定要记清楚。

总结

StampLock的使用看上去有点复杂,但是如果你能理解乐观所背后的原理,使用起来还是比较流畅的。

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

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

相关文章

Docker安装Skywalking APM分布式追踪系统

Skywalking是一个应用性能管理(APM)系统,具有服务器性能监测,应用程序间调用关系及性能监测等功能,Skywalking分为服务端、管理界面、以及嵌入到程序中的探针部分,由程序中的探针采集各类调用数据发送给服务端保存,在管…

novnc 和 vnc server 如何实现通信?原理?

参考:https://www.codenong.com/js0f3b351a156c/

随机微分方程

应用随机过程|第7章 随机微分方程 见知乎:https://zhuanlan.zhihu.com/p/348366892?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

复习3-5天【80天学习完《深入理解计算机系统》】第七天

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示&#…

Linux与bash(基础内容一)

一、常见的linux命令: 1、文件: (1)常见的文件命令: (2)文件属性: (3)修改文件属性: 查看文件的属性: ls -l 查看文件的属性 ls …

神经网络基础-神经网络补充概念-33-偏差与方差

概念 偏差(Bias): 偏差是模型预测值与实际值之间的差距,它反映了模型对训练数据的拟合能力。高偏差意味着模型无法很好地拟合训练数据,通常会导致欠拟合。欠拟合是指模型过于简单,不能捕捉数据中的复杂模式…

基于java在线读书与分享论坛设计与实现

摘 要 互联系统的技术在如今的社会中,应用的越来越广泛,通过互联系统我们可以更方便地进行办公,也能够在系统上就能处理很多日常的事务。互联系统的技术的发展,也是人们日常中接触更多的一项技术。随着互联系统的发展,…

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 摘要当前的检测sota模型网络架构swin Transformer和Vision Transformer的不同之处整体架构Patch Partition结构Linear Embedding结构Swin Transformer Block结构 Patch MergingW-MSAMSA模块计算量W-M…

学习Vue:Vue3 VS Vue2

Vue 3作为Vue.js的最新版本,带来了一系列令人激动的新特性和改进,让开发者们在构建现代Web应用时体验更加顺畅和高效。本文将全面介绍Vue 3相对于Vue 2的改进,重点解释Composition API的使用,以及新引入的Teleport和Suspense等特性…

Genoss GPT简介:使用 Genoss 模型网关实现多个LLM模型的快速切换与集成

一、前言 生成式人工智能领域的发展继续加速,大型语言模型 (LLM) 的用途范围不断扩大。这些用途跨越不同的领域,包括个人助理、文档检索以及图像和文本生成。ChatGPT 等突破性应用程序为公司进入该领域并开始使用这项技术进行构建铺平了道路。 大公司正…

如何发布自己的小程序

小程序的基础内容组件 text&#xff1a; 文本支持长按选中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染为对应的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

MySql过滤重复数据

假设模型表是: 1. 根据单字段过滤: SELECT user_name, COUNT(*) as count FROM sys_user GROUP BY user_name HAVING count > 1;结果: 2. 根据多个字段查询重复数据 SELECT user_name, email, COUNT(*) as count FROM sys_user GROUP BY user_name, email HAVING count…

[centos]设置主机名

1、设置 hostnamectl set-hostname 名字 2、查看是否生效 hostnamectl status 3、打开一个新链接就可以了

log4j教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Log4j是Apache的一个开源项目&#xff0c;通过使用Log4j&#xff0c;我们可以控制日志信息输送的目的地是控制台、文件、GUI组件&#xff0c;甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等&#xff1b;我们也可以控制每一条日志的输出格式&#xff1b;…

[python] 使用Jieba工具中文分词及文本聚类概念

前面讲述了很多关于Python爬取本体Ontology、消息盒InfoBox、虎扑图片等例子&#xff0c;同时讲述了VSM向量空间模型的应用。但是由于InfoBox没有前后文和语义概念&#xff0c;所以效果不是很好&#xff0c;这篇文章主要是爬取百度5A景区摘要信息&#xff0c;再利用Jieba分词工…

hive--给表名和字段加注释

1.建表添加注释 CREATE EXTERNAL TABLE test(loc_province string comment 省份,loc_city string comment 城市,loc_district string comment 区,loc_street string comment 街道,)COMMENT 每日数据处理后的表 PARTITIONED BY (par_dt string) ROW FORMAT SERDEorg.apache.had…

学习Vue:响应式原理与性能优化策略

性能优化是Vue.js应用开发中的一个关键方面&#xff0c;而深入了解响应式原理并采用有效的性能优化策略可以显著提升应用的性能。本文将解释响应式原理并介绍一些性能优化策略&#xff0c;旨在帮助您构建高性能的Vue.js应用。 响应式原理 Vue.js的响应式原理是通过利用Object.…

PHP在线客服系统推荐

在当今数字化时代&#xff0c;企业客户服务的重要性不容忽视。为了提供卓越的客户体验&#xff0c;许多企业正在寻找PHP在线客服系统。这种系统不仅可以满足客户的需求&#xff0c;还能提升企业的形象。本文将深入探讨PHP在线客服系统的一些有趣话题。 理解PHP在线客服系统 PHP…

71 # 协商缓存的配置:通过内容

对比&#xff08;协商&#xff09;缓存 比较一下再去决定是用缓存还是重新获取数据&#xff0c;这样会减少网络请求&#xff0c;提高性能。 对比缓存的工作原理 客户端第一次请求服务器的时候&#xff0c;服务器会把数据进行缓存&#xff0c;同时会生成一个缓存标识符&#…

Transformer是什么,Transformer应用

目录 Transformer应用 Transformer是什么 Transformer应用:循环神经网络 语言翻译:注重语句前后顺序 RNN看中单个特征; CNN:看中特征之间时序性 模型关注不同位置的能力 Transformer是什么 Transformer是一个利用注意力机制来提高模型训练速度的模型。关于注意力机…