Java 8 StampedLocks与ReadWriteLocks和同步

Blog_key_

同步部分就像访问您的岳父母。 您希望尽可能少出现。 关于锁定,规则是相同的–您想花费最短的时间在关键区域内获取锁定,以防止形成瓶颈。

锁定的核心语言惯用法一直是用于方法和离散块的synced关键字。 这个关键字实际上已硬连接到HotSpot JVM中。 我们在代码中分配的每个对象,无论是String,Array还是成熟的JSON文档,都在本机GC级别的标头中内置锁定功能。 对于JIT编译器(根据特定锁的特定状态和争用级别来编译和重新编译字节码)也是如此。

同步块的问题在于它们全有还是全无 -关键部分中不能有多个线程。 在消费者/生产者方案中,这尤其令人a舌,其中一些线程试图专门编辑一些数据,而另一些线​​程只是试图读取数据并且可以共享访问权限。

ReadWriteLocks旨在成为此的完美解决方案。 您可以指定哪些线程阻止其他所有人(作家),以及哪些线程与其他人一起使用以消费内容(读者)。 一个快乐的结局? 不怕。

与同步块不同,RW锁不是JVM内置的,并且具有与凡人代码相同的功能。 尽管如此,要实现锁定习惯,您仍然需要指示CPU自动执行特定操作或以特定顺序执行操作,以避免出现竞争情况。 传统上,这是通过进入JVM的神奇门户漏洞- 不安全的类来完成的。 RW锁使用比较和交换(CAS)操作将值直接设置到内存中,作为其线程排队算法的一部分。

即便如此,RWLocks仍然不够快,有时甚至被证明确实很慢 ,以至于不值得为此烦恼。 但是,正在寻求帮助,JDK的好伙伴们没有放弃,现在又有了新的StampedLock 。 该RW锁采用了Java 8 JDK中新增的一组算法和内存隔离功能,以帮助使此锁更快,更可靠。

它兑现了诺言吗? 让我们来看看。

使用锁。 从表面上看,StampedLocks使用起来更复杂。 他们采用的邮票概念是很长的值,可以用作任何锁定/解锁操作使用的票证。 这意味着要解锁R / W操作,您需要为其传递相关的锁定标记。 通过错误的印章,您将面临例外甚至更糟的意外风险。

另一个需要牢记的关键是,与RWLocks不同,StampedLocks 不可重入 。 因此,尽管它们可能更快,但它们有一个缺点,那就是线程现在可以使自己陷入僵局。 实际上,这意味着比以往任何时候都更应该确保锁和图章不会逸出其封闭的代码块。

long stamp = lock.writeLock();  //blocking lock, returns a stamptry {write(stamp); // this is a bad move, you’re letting the stamp escape
}finally {lock.unlock(stamp);// release the lock in the same block - way better
}

我对这种设计的另一个讨厌之处是,邮票被用作长期价值,对您实际上没有任何意义。 我希望使用锁定操作来返回一个描述印记的对象-其类型(R / W),锁定时间,所有者线程等。这将使调试和记录更加容易。 但是,这可能是有意的,它旨在防止开发人员在代码的不同部分之间传递标记,并且还节省了分配对象的成本。

乐观锁 。 就此锁的新功能而言,最重要的部分是新的乐观锁模式。 研究和实践经验表明,读操作在大多数情况下都无法与写操作抗衡。 结果,获得一个成熟的读锁可能被证明是过大的。 更好的方法可能是继续执行读取,并在读取的最后查看该值是否实际上已被修改。 如果是这种情况,您可以重试读取,或升级到较重的锁。

long stamp = lock.tryOptimisticRead(); // non blockingread();if(!lock.validate(stamp)){ // if a write occurred, try again with a read locklong stamp = lock.readLock();try {read();}finally {lock.unlock(stamp);}
}

选锁的最大麻烦之一是,它在生产中的实际行为将根据应用程序状态而有所不同。 这意味着锁定习语的选择不能凭空完成,而必须考虑代码将在其下执行的实际条件。

并发读取器线程与写入器线程的数量将更改您应使用的锁–同步段或RW锁。 由于这些数字在JVM的生命周期中会发生变化,因此这变得更加困难,具体取决于应用程序状态和线程争用。

为了说明这一点,我对不同锁定级别和R / W线程组合下的四种锁定模式进行了压力测试-同步,RW锁定,Stamped RW锁定和RW乐观锁定。 读取器线程将消耗计数器的值,而写入器线程将其从0递增到1M。

5个读取器与5个写入器堆叠5个并发读取器和5个写入器线程,我们看到加盖的锁发光了,性能比同步提高了3倍。 RW锁定也表现良好。 奇怪的是,乐观锁在表面上应该是最快的,但实际上却是最慢的

04

1 0个读者与10个作家:接下来,我将争用级别提高到10个作家和10个读者线程。 在这里,事情开始发生重大变化。 RW锁现在比在相同级别上执行的加盖和同步锁一个数量级。 请注意,令人惊讶的是乐观锁仍然是慢速加盖的RW锁。

01

16位读者与4位作家:接下来,我保持较高的竞争水平,同时又使平衡趋于有利于读者线程:16位读者与4位作家。 RW锁继续说明了其被替换的原因- 速度慢一百倍 。 Stamped和Optimistic的性能很好,同步性也不差。

02

19位读者与1位读者:最后,我研究了单个作者线程对19位读者的影响。 请注意,结果要慢得多,因为单线程需要更长的时间才能完成工作。 在这里,我们得到一些非常有趣的结果。 毫不奇怪,RW锁需要无穷大才能完成。 但是,冲压锁定的性能并没有好得多……乐观锁定显然是赢家,比RW锁定高100倍。即使如此,请记住,这种锁定方式可能会使您失败,因为在此期间可能会发生写入器。 我们忠实的老客户,同步化继续取得可喜的成果。

03

完整的结果可以在这里找到……硬件:MBP四核i7。

基准代码可以在这里找到。

结论

似乎平均而言,内在同步锁仍可提供总体上最佳的性能。 即使这样,这里的意思并不是说它将在所有情况下都表现最佳。 主要是为了表明, 将代码投入生产之前 ,应该基于测试预期的争用级别以及读取器和写入器线程之间的划分来选择锁定习惯用法。 否则,您将冒着严重的生产调试痛苦的风险。

在此处了解有关StampedLocks的更多信息 。

对基准有疑问,意见或建议吗? 让我知道!

翻译自: https://www.javacodegeeks.com/2014/06/java-8-stampedlocks-vs-readwritelocks-and-synchronized.html

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

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

相关文章

MSN on 2/16/2009

转载于:https://www.cnblogs.com/zxlin25/archive/2009/02/16/1391207.html

开发微信小程序中SSL协议的申请、证书绑定、TLS 版本处理等

在上篇随笔《基于微信小程序的系统开发准备工作》介绍了开发微信小程序的一些前期的架构设计、技术路线 、工具准备等方面内容,本篇随笔继续这个步骤,逐步介绍我们实际开发过程中对SSL协议的申请及后期处理过程,包括证书的IIS端口绑定&#x…

POJ 3253 Fence Repair

POJ 3253 Fence Repair 题目链接:http://poj.org/problem?id3253 题目大意 农夫约翰想修理牧场周围的一小段篱笆。他测量了栅栏,发现他需要N(1≤N≤20,000)块木板,每块长度为整数Li(1≤Li≤50,000)。然后,他买了一块长木板&#…

【面向对象】对比JavaScript、Go、Ada、Python、C++、Java、PHP的访问限制。

在不同编程语言中,控制成员(变量、方法、类等)可见性的机制不尽相同。以下是对比JavaScript、Go、Ada、Python、C、Java、PHP所使用的访问限制关键字和约定: 一、JavaScript ### JavaScript访问限制 早期的JavaScript并没有类似…

C#各类访问权限,封装,修饰符

C#各类访问权限,封装,修饰符。 (1) Pubilc :任何公有成员可以被外部的类访问。(2) Private :只有同一个类中的函数可以访问它的私有成员。(3) Protected :该类内部和继承类中可以访问。(4) internal : 同一个程序集的对…

在Java 8中使用Stream API列出ZIP文件的内容

在Java 8 java.util.zip.ZipFile配备了stream方法,该方法可以非常轻松地浏览ZIP文件条目。 在此博客文章中,我将展示许多示例,这些示例显示了我们可以如何快速浏览ZIP文件条目。 注意:就本博客而言,我将一个GitHub存储…

tomcat5下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法...

tomcat5下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法 【标 题】:tomcat5下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法【关键字】:tomcat5,jsp,getOutpu…

Web API应用架构设计分析(1)

Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端(包括浏览器,手机和平板电脑等移动设备)的框架, ASP.NET Web API 是一种用于在 .NET Framework 上构建 RESTful 应用程序的理想平台。本文主要以AS…

记手机端 下拉加载新数据

$(#container).unbind("scroll").bind(scroll,function(e){var sum this.scrollHeight - 5;console.log(sum)console.log($(this).scrollTop() $(this).height())if(sum <$(this).scrollTop() $(this).height()){ getmore();       }     }) $(#co…

一个切图仔的 CSS 笔记

1&#xff0c;flexbox~注意&#xff0c;设为 Flex 布局以后&#xff0c;子元素的float、clear和vertical-align属性将失效。 在ios8上要加上前缀 display: -webkit-box; display: -webkit-flex; display: -webkit-box; /* Chrome 4, Safari 3.1, iOS Safari 3.2 */ display: …

如何使用JPA Type Converter加密数据

几天前&#xff0c;我读了Bear Giles关于2012年使用JPA监听器进行数据库加密的有趣文章。他讨论了对加密解决方案的要求&#xff0c;并提供了JPA监听器的代码示例。 他的主要要求是&#xff1a; 提供不影响应用程序的透明加密&#xff0c; 能够在部署时添加加密&#xff0c; …

go语言的排序和去重

go语言的排序&#xff1a; https://blog.csdn.net/u010983881/article/details/52460998 go语言去重&#xff1a; https://blog.csdn.net/qq_27068845/article/details/77407358 通过构造set去重&#xff08;go中没有set&#xff09;&#xff1a; https://studygolang.com/arti…

MapXtreme2008中操作矢量符号和定制符号

本文部分说明内容摘自网络文章&#xff0c;经过本人在MapXtreme2008中编写相关的演示例子&#xff0c;详细说明如何操作MapXtreme2008提供的矢量符号和定制符号。 MapXtreme 在其安装过程中自动安装 10 种 MapInfo 特定的 TrueType 字体。这些字体为用户提供了字形符号选择&am…

指甲之指甲长期没有甲半月弧(二)

中医的精是构成人体的基本物质。精来源于先天的禀赋及后天饮食营养。中医认为&#xff0c;气不耗归于肝为血&#xff0c;血不耗归于肾为精&#xff0c;精不耗归于骨为髓。 半月痕正是人体精髓的窗口。而半月痕的变化&#xff0c;犹如汽车上的油表一样&#xff0c;它会告颂人体&…

编写干净的测试–从配置开始

很难为干净的代码找到一个好的定义&#xff0c;因为我们每个人都有自己的单词clean的定义。 但是&#xff0c;有一个似乎是通用的定义&#xff1a; 干净的代码易于阅读。 这可能会让您感到有些惊讶&#xff0c;但是我认为该定义也适用于测试代码。 使测试尽可能具有可读性是我…

集合类(二)

关于迭代器&#xff08;Iterator&#xff09;的两种迭代机制&#xff1a;fail-fast 和 fail-safe fail-fast 机制&#xff1a;遍历集合时&#xff0c;当集合结构被修改&#xff0c;会抛出Concurrent Modification Exception 触发条件&#xff1a;单线程在遍历过程修改&#xff…

jQuery-弹幕

该方法可能有bug&#xff0c;毕竟简单粗暴 <!DOCTYPE html><html> <head> <meta charset"UTF-8"> <title></title> <script type"text/javascript" src"js/jquery-1.11.0.js"></script> <s…

ubuntu下C编程,编译基础( 转)

buntu下C编程&#xff0c;编译基础 C 编程中相关文件后缀 .a静态库 (archive).cC源代码&#xff08;需要编译预处理&#xff09;.hC源代码头文件.iC源代码&#xff08;不需编译预处理&#xff09;.o对象文件.s汇编语言代码.so动态库单个源文件生成可执行程序 下面是一个简单的…

转载:97特瑞心得

单位里无聊打着玩的心得&#xff0c;写了段时间了&#xff0c;基本是哪天想到什么就打上去&#xff0c;狗屁不通的地方请大家包涵。97特瑞玩了有10年多了吧,97刚出来的时候就玩的特瑞&#xff0c;别人都八神&#xff0c;萝卜特&#xff0c;克拉克的时代我就坚持用特瑞&#xff…

Hibernate二级/查询缓存的陷阱

这篇文章将介绍如何设置Hibernate二级和查询缓存&#xff0c;它们如何工作以及最常见的陷阱。 休眠二级缓存是用于存储实体数据的应用程序级缓存。 查询缓存是一个单独的缓存&#xff0c;仅存储查询结果。 这两个缓存实际上是并存的&#xff0c;因为在很多情况下&#xff0c;…