Java 8 LongAdders:管理并发计数器的正确方法

博客羊

我只是喜欢新玩具,而Java 8有很多 。 这次我想谈谈我的最爱之一-并发加法器。 这是一组用于管理由多个线程编写和读取的计数器的新类。 新的API有望显着提高性能,同时仍然使事情变得简单明了。

自从多核架构问世以来人们一直在管理并发计数器,让我们看一看到目前为止Java提供了哪些选项,以及与新API相比它们的性能如何。

脏计数器 –这种方法意味着您正在多个线程之间的常规对象或静态字段中进行写入/读取操作。 不幸的是,这有两个原因。 首先是在Java中,A + = B操作不是原子操作。 如果打开输出字节码,将至少看到四条指令-一个用于将堆中的字段值加载到线程堆栈中,第二个用于加载增量,第三个用于添加增量,第四个用于设置结果进入领域。

如果在同一个内存位置同时有多个线程同时执行此操作,则极有可能错过写操作,因为一个线程可以覆盖另一个线程的值(又称“读取-修改-写入”) 。 与此相关的还有另一个讨厌的角度,那就是价值的波动性。 下面的更多内容。

这是一个菜鸟错误,而且很难调试。 如果您遇到了在您的应用程序中执行此操作的任何人,我想问一个小小的忙。 在数据库中搜索“ Tal Weiss”。 如果您在那里看到我–删除我的记录。 我会更安全的。

同步 -这是最基本的并发习惯用法,它在读取或写入值时会阻塞所有其他线程。 当它起作用时,这是将代码转换为DMV行的可靠方法。

RWLock –基本Java锁的这种稍微复杂的版本,使您可以区分更改值和需要阻止其他线程的线程与仅读取而不需要关键部分的线程。 尽管这可能更有效(假设编写器的数量很少),但这是一个相当不错的方法,因为在获取写锁时,您将阻止所有其他线程的执行。

易失性 -这个相当容易被误解的关键字实际上指示JIT编译器取消优化运行时机器代码,以便其他线程可以立即看到对该字段的任何修改。

这使某些JIT编译器最喜欢的优化工作失去了按分配分配给内存的顺序进行。 再说一次 你听到了 JIT编译器可能会更改对字段进行分配的顺序。 这种神秘的小策略(也称为before-before )使它可以最小化程序访问全局堆所需的次数,同时仍确保您的代码不受其影响。 偷偷摸摸的…

那么什么时候应该使用易失性计数器? 如果只有一个线程在更新值,而有多个线程在使用它,那么这是一个非常好的策略–根本没有争用。

那么为什么不总是问它呢? 因为当一个以上的线程正在更新该字段时,这不能很好地工作。 由于A + = B不是原子的,因此您有重写别人的写的风险。 在Java 8之前,您需要使用AtomicInteger。

AtomicInteger-这组类使用CAS(比较和交换)处理器指令来更新计数器的值。 听起来不错,不是吗? 好,是的,不是。 这很有效,因为它利用直接的机器代码指令来设置该值,而对其他线程的执行影响最小。 缺点是,如果由于与另一个线程的争用而无法设置该值,则必须重试。 在竞争激烈的情况下,这可能会变成自旋锁,其中线程必须不断尝试并在无限循环中设置该值,直到成功为止。 这不是我们想要的。 输入带有LongAdders的Java 8。

Java 8 Adders –这是一个非常酷的新API,我迫不及待想要了解它! 从使用角度来看,它与AtomicInteger非常相似。 只需创建一个LongAdder并使用intValue()和add()即可获取/设置值。 魔术发生在幕后。

此类的作用是当直接CAS由于争用而失败时,它将增量存储在为该线程分配的内部单元对象中。 然后在调用intValue()时将待处理单元格的值加到总和中。 这减少了返回和CAS或阻止其他线程的需要。 很聪明的东西!

这么好说吧–让我们看看这只小狗在行动。 我们已经建立了以下基准测试:将计数器重置为零,并开始使用多个线程进行读取和递增。 当计数器达到10 ^ 8时停止。 我们在4核i7处理器上运行基准测试。

我们使用总共十个线程来运行基准测试-五个用于写作,五个用于阅读,因此我们在这里势必会引起严重的争论:

  • 请注意,肮脏和易变的风险值都将覆盖。

table_april-16_02-2

  • 代码在这里可用

底线

  • 并发加法器洁净室的性能比原子整数提高60-100%
  • 除了锁定时,添加线程没有什么区别。
  • 请注意,使用同步锁或RW锁会给您带来巨大的性能损失-慢一个数量级!

如果您已经有机会在代码中使用这些类,那么我很乐意听到。

  • 补充阅读– Brian Goetz关于Java并发性。

翻译自: https://www.javacodegeeks.com/2014/04/java-8-longadders-the-right-way-to-manage-concurrent-counters.html

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

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

相关文章

asp: menu 父级选中

最近比较忙,其中一个项目中用到了菜单,结果User比较难搞定,非要什么有父级菜单选中的样式,就像windows的菜单效果差不多的那种,鼠标飘在子结点上,父结点也要保留反白的选中样式,唉,U…

java 内部类 单例_Java单例模式的几种实现

一:静态内部类实现单例模式原理:通过一个静态内部类定义一个静态变量来持有当前类实例,在类加载时就创建好,在使用时获取。缺点:无法做到延迟创建对象,在类加载时进行创建会导致初始化时间变长。public cla…

JS中ptototype和__proto__的关系

学到原型的时候感觉头都大了/(ㄒoㄒ)/~~ 尤其是ptototype和__proto__ 傻傻分不清 通过多番查找资料,根据自己的理解,总结如下: 一、构造函数: 构造函数:通过new关键字可以用来创建特定类型的对象的函数。比如像Obje…

函数与匿名函数

函数与匿名函数一、函数 在计算机科学中,函数是程序负责完成某项特定任务的代码单元,具有一定的独立性。 1.函数的定义 在Python中,函数在定义时需要满足这样的规则: 使用关键字def引导;def后面是函数的名称&#xff0…

[最短路]飞行

题目描述 WFYZ的校园很大,这里生活着很多生物,比如住在钟楼上的的鸽子,其中鸽子冉冉和她的妹妹凝凝白天在不同的地方吃虫,而在晚上她们都回到钟楼休息。她俩是两只懒鸟,于是提出了一个计划,尽量减少她们在飞…

Java状态和策略设计模式之间的差异

为了在Core Java应用程序中正确使用状态和策略设计模式,对于Java开发人员清楚地了解它们之间的区别很重要。 尽管状态和策略设计模式的结构相似,并且都基于开放式封闭设计原则,从SOLID设计原则表示为“ O”,但它们在意图上完全不同…

【原创】系统分析师--任重而道远

今天查到了系统分析师的成绩。有坏消息,也有好消息。 坏消息当然就是意料之中的没过了,好消息是我基本上没有花什么时间去准备,但是结果却比想象中的要好。 案例分析这一场过了。基础知识差几分,论文只是及格分的一半&#xf…

XML文档的简易增删查改

dom4j解析一、利用dom4j操作元素节点 1.查询第一本书的书名,并输出到控制台 2.给第一本书添加一个特价节点, 并修改第一本书的售价节点的内容为19.8元 3.删除第二本书的作者节点二、利用dom4j操作属性节点 1.给第一本书添加一个属性,如:出版社…

廖雪峰Java3异常处理-1错误处理-2捕获异常

1捕获异常 1.1 finally语句保证有无错误都会执行 try{...}catch (){...}finally{...} 使用try...catch捕获异常可能发生异常的语句放在try{...}中使用catch捕获对应的Exception及其子类1.2 捕获多个异常 try{...} catch() {...} catch(){...}finally{..} 使用多个catch子句&…

更新数据库

方法一:在对SQL数据库进行更新时,用CommandBuilder对像来自动构建sql命令,来起到更新的作用;这种方法用起来比较方便,具体代码如下: 以下代码都在xp系统下测试通过 环境:vs.net2005 \ sql server 2000\xpus…

在崩溃或断电后测试Lucene的索引耐久性

Lucene有用的事务功能之一是索引持久性 ,它可以确保一旦成功调用IndexWriter.commit ,即使操作系统或JVM崩溃或断电,或者您杀死-KILL JVM进程,重启后索引也将保持完整(未损坏),并将反映崩溃前的…

Bash 脚本 set 命令教程

http://www.ruanyifeng.com/blog/2017/11/bash-set.html set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题。本文介绍它的基本用法,让你可以更安心地使用 Bash 脚本。 一、简介 我们知道,Bash 执行脚…

Jmeter、postman、python 三大主流技术如何操作数据库?

1、前言 只要是做测试工作的,必然会接触到数据库,数据库在工作中的主要应用场景包括但不限于以下: 功能测试中,涉及数据展示功能,需查库校验数据正确及完整性;例如商品搜索功能 自动化测试或性能测试中&a…

[转][HTML]css属性

1、字体属性(type)font-family(使用什么字体)font-style(字体的样式,是否斜体):normal/italic/obliquefont-variant(字体大小写):normal/small-capsfont-weight(字体的粗细):normal/bold/bolder/lithterfont-size(字体的大小)&…

7-OKHttp使用详解,步骤挺详细的,适合初学者使用!

OKHttp使用详解,步骤挺详细的,适合初学者使用! 一,OKHttp介绍 okhttp是一个第三方类库,用于android中请求网络。 这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和Leak…

变量与递归函数

变量与递归函数一、变量 变量分为全局变量和局部变量。 python中全局变量和局部变量的最大区别在于局部变量只能通过函数去访问,而全局变量可以直接访问。 举个例子: name linxu #全局变量 def change_name():namepython #局部变量print(name) …

使用MOXy 2.5.1快速且有点脏的JSON模式生成

因此,这些天我正在为即将推出的Oracle云服务开发新的REST API,因此我需要做的一件事情就是能够为模型中的bean自动生成JSON模式。 我正在使用MOXy从POJO生成JSON,从EclipseLink 2.5.1版本开始,它现在具有从bean模型生成JSON模式的…

手机端input[type=date]的placeholder不起作用

<div class"input clearfix"><label class"fl">起始日期</label><input class"fl text_date" type"date" name"" value"" placeholder"年/月/日" /></div><div cla…

Python中的TCP编程,实现客户端与服务器的聊天(socket)

参考大神blog:自己再写一个 https://blog.csdn.net/qq_31187881/article/details/79067644转载于:https://www.cnblogs.com/studybrother/p/10306903.html

利用ASP.NET向服务器上传文件[转]

文件上传技术是一个很实用的技术&#xff0c;有着很广泛的应用&#xff0c;在ASP.NET自身的前一个版本ASP里实现这个功能&#xff0c;就必须使用第三方的组件或者自己开发组件了&#xff0c;现在&#xff0c;用ASP.NET实现起来就简单得多了&#xff0c;我们不需要使用任何组件就…