java8longadders:管理并发计数器的正确方式-java开发java经验技巧

java8longadders:管理并发计数器的正确方式-java开发java经验技巧

ID:30775778

大小:60.00 KB

页数:5页

时间:2019-01-03

java8longadders:管理并发计数器的正确方式-java开发java经验技巧_第1页
java8longadders:管理并发计数器的正确方式-java开发java经验技巧_第2页
java8longadders:管理并发计数器的正确方式-java开发java经验技巧_第3页
java8longadders:管理并发计数器的正确方式-java开发java经验技巧_第4页
java8longadders:管理并发计数器的正确方式-java开发java经验技巧_第5页
资源描述:

《java8longadders:管理并发计数器的正确方式-java开发java经验技巧》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

1、Java8LongAdders:管理并发计数器的正确方式-编程开发技术Java8LongAdders:管理并发计数器的正确方式本文illImportNew-will翻译自takipiblogo欢迎加入翻译小组。转载诘见文末要求。我只是喜欢新鲜的事物,ifUJava8冇很多新东四。这次我想讨论其屮我最喜欢的之一:并发加法器。这是一个新的类集合,他们用来管理被多线程读写的计数器。这个新的API在显著提升性能同吋,仍然保持了简单直接的特点。多核架构到來之后人们就解决着并发计数器,让我们來看看到现在为止Java

2、提供了哪些解决并发计数器的选项,并对比一下他们与新API的性能。脏计数器-这种方法意味着一个常规对彖或静态屈性正在被多线程读写。不幸的是,由于两个原因这行不通。原因之一,在Java中A+=B操作不是原子的。如果你打开输出字节码,你将至少看到四个指令——第一个用来将属性值从堆加载到线程栈,第二个用來加载delta,第三个用來把它们相加,第四个用來将结果重新分配给属性值。如果多个线程同时作用于同一块内存单元,写操作冇很大机会丢失,因为一个线程可以覆盖另一个线程的值(乂名“读-修改-写”),另一个令人不快的是

3、这种情况下你不得不处理值的冲突,述有更坏的情况。这是相当菜鸟的一个问题,而II超级难调试。如果你确实发现有人在你的应用中这么做的话,我想要你帮个小忙。在你的数据库小搜索“TaiWeiss”,如果存在我的记录,请删除,这样我会觉得安全些。Synchronized-最基本的并发用语,它在读写一个值的时候会阻塞所有想读写该值的其他线程。虽然它是可行的,但你的代码却注定要被转向DMVline。读写锁-基本J&眩锁的略复杂版本,它使你能够区分修改值并且需要阻塞其他线程的线程和仅是读取值并且不需要临界区的线程。虽然

4、这更有效率(假设写线程数量很少),但由于当你获取写锁的时候阻塞了所冇其他线程的执行,这真是一个“漂亮”的方法。事实上,只有当你了解到相比读线程,写线程的数量极大地受限吋它才真正是-个好方法。Volatile-这个关键词非常容易被误解,它指示JIT编译器重新优化运行时机器码,使得屈性的任何修改对其他线程都是即时可见的。这将导致一些jrr处理内存分配的顺序这项jrr编译器最喜爱的优化失效。你再说一遍?是的,你没有听错。jit编译器可以改变属性分配的顺序。这个神秘的小策略(又叫happens-before)能

5、够最小化程序访问全局堆的次数,同时仍然确保你的代码没有被影响。真是相当隐蔽…所以什么时候应该使用volatile处理计数器呢?如果你仅有一个线程更新值并且多个线程读取它,这时使用volatile无疑是一个真正好的策略。那为什么不总是使用它呢?因为当多个线程同时更新屈性的时候它不能很好的工作。由于A+二B不是原子操作,这将带来覆盖其他写操作的风险。在Java8之前,处理这种情况你需要使用的是AtomiclntegeroAtomiclnteger-这组类使用CAS(比较并交换)处理器指令来更新计数器的值。听

6、起来不错,真的是这样吗?是也不是。好的一面是它通过一个直接机器码指令设置值时,能够最小程度地影响其他线程的执行。坏的一面是如果它在与其他线程竞争设置值时失败了,它不得不再次尝试。在高竞争F,这将转化为一个自旋锁,线程不得不持续尝试设置值,无限循环直到成功。这可不是我们想要的方法。让我们进入Java8的LongAdderSoJava8加法器-这是一个如此酷的新API以至于我一宜在滔滔不绝地谈论它。从使用的角度看它与Atomiclnteger非常相似,简单地创建一个LongAdder实例,并使用intVal

7、ueO和add()来获取和设置值。神奇的地方发生在幕后。这个类所做的事情是当一个直接CAS由于竞争失败时,它将delta保存在为该线程分配的一个内部单元对彖中,然后当intValue()被调用时,它会将这些临时单-兀的值再相加到结果和屮。这就减少了返回重新CAS或者阻塞其他线程的必要。多么聪明的做法!好吧,已经说的够多了-让我们看看这个类的实际表现吧。我们设立了卜•面的基准测试-通过多线程将一个计数器增加到10飞。我们用总共10个线程来运行这个测试-5个写操作,5个读操作。测试机器仅有一个四核的i7处理

8、器,因此测试-定会产生一些严重的竞争:DIRTYVOLATILESYNCHRONIZEDRWLOCKATOMI1129454弓120911335552591110146791317713267632661079407717157180287312811243662161231849233262108947231636617997531171117453516647155151301411003615174211388672759114m35

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。