接触到AtomicLong的原因是在看guava的LoadingCache相关代码时,关于LoadingCache,其实思路也非常简单清晰:用模板模式解决了缓存不命中时获取数据的逻辑,这个思路我早前也正好在项目中使用到。
final void retryUpdate( long x, HashCode hc, boolean wasUncontended) { int h = hc.code; boolean collide = false ; // True if last slot nonempty for (;;) { Cell[] as; Cell a; int n; long v; if ((as = cells) != null && (n = as.length) > 0 ) { // 分支1 if ((a = as[(n - 1 ) & h]) == null ) { if (busy == 0 ) { // Try to attach new Cell Cell r = new Cell(x); // Optimistically create if (busy == 0 && casBusy()) { boolean created = false ; try { // Recheck under lock Cell[] rs; int m, j; if ((rs = cells) != null && (m = rs.length) > 0 && rs[j = (m - 1 ) & h] == null ) { rs[j] = r; created = true ; } } finally { busy = 0 ; } if (created) break ; continue ; // Slot is now non-empty } } collide = false ; } else if (!wasUncontended) // CAS already known to fail wasUncontended = true ; // Continue after rehash else if (a.cas(v = a.value, fn(v, x))) break ; else if (n >= NCPU || cells != as) collide = false ; // At max size or stale else if (!collide) collide = true ; else if (busy == 0 && casBusy()) { try { if (cells == as) { // Expand table unless stale Cell[] rs = new Cell[n << 1 ]; for ( int i = 0 ; i < n; ++i) rs[i] = as[i]; cells = rs; } } finally { busy = 0 ; } collide = false ; continue ; // Retry with expanded table } h ^= h << 13 ; // Rehash h ^= h >>> 17; h ^= h << 5 ; } else if (busy == 0 && cells == as && casBusy()) { //分支2 boolean init = false ; try { // Initialize table if (cells == as) { Cell[] rs = new Cell[ 2 ]; rs[h & 1 ] = new Cell(x); cells = rs; init = true ; } } finally { busy = 0 ; } if (init) break ; } else if (casBase(v = base, fn(v, x))) break ; // Fall back on using base } hc.code = h; // Record index for next time } |
可以看到,LongAdder确实用了很多心思减少并发量,并且,每一步都是在”没有更好的办法“的时候才会选择更大开销的操作,从而尽可能的用最最简单的办法去完成操作。追求简单,但是绝对不粗暴。
————————————————分割线——————————————————————-
昨天在coolshell 投稿后 (文章在这里) 和左耳朵耗子简单讨论了下,发现左耳朵耗子对读者思维的引导还是非常不错的,在第一次发现这个类后,对里面的实现又提出了更多的问题,引导大家思考,值得学习,赞一个~
我们 发现的问题有这么几个:
1. jdk 1.7中是不是有这个类?
我确认后,结果如下: jdk-7u51版本上 上还没有 但是jdk-8u20 版本上已经有了。代码基本一样 ,增加了对double类型的支持和删除了一些冗余的代码。
2. base有没有参与汇总?
base在调用intValue等方法的时候是会汇总的:
3. base的顺序可不可以调换?
左耳朵耗子,提出了这么一个问题: 在add方法中,如果cells不会为空后,casBase方法一直都没有用了?
因此,我想可不可以调换add方法中的判断顺序,比如,先做casBase的判断,结果是 不调换可能更好,调换后每次都要CAS一下,在高并发时,失败几率非常高,并且是恶性循环,比起一次判断,后者的开销明显小很多,还没有副作用。因此,不调换可能会更好。
4. AtomicLong可不可以废掉?
我的想法是可以废掉了,因为,虽然LongAdder在空间上占用略大,但是,它的性能已经足以说明一切了,无论是从节约空的角度还是执行效率上,AtomicLong基本没有优势了,具体看这个测试(感谢coolshell读者Lemon的回复):http://blog.palominolabs.com/2014/02/10/java-8-performance-improvements-longadder-vs-atomiclong/
原文地址: http://coolshell.cn/articles/11454.html
相关推荐
主要介绍了Java并发工具类LongAdder原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
通过对代码的流程分析,一步一步拆解,将源码解读变得简单
本文给出了使用这些方法实现自增的代码演示,并通过多线程测试比较了它们的效率。测试表明,LongAdder的效率最高,LongAccumulator次之,AtomicInteger再次之,synchronized最慢。同时,本文也对这些方法的原理进行...
3. 新的并发工具:Java 17还引入了新的并发工具,如LongAdder和LongAccumulator。这些工具提供了更好的并发性能,并使开发人员能够更轻松地编写高并发的应用程序。 4. 更好的类型推断:Java 17改进了局部变量类型...
主要给大家介绍了关于JDK8中新增的原子性操作类LongAdder的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧。
第6章介绍了 Java 8中为并行计算做的新的改进, 包括并行流、 CompletableFuture、 StampedLock和LongAdder。第7章主要介绍了高并发框架Akka的基本使用方法,并使用Ak:ka框架实现了 个简单的粒子群算法, 模拟超高...
看了一下资源都没有java8新特性DoubleAccumulator的使用例子,所以分享一下这个的使用另外的其他3个类工具的使用类似DoubleAdder,LongAccumulator,LongAdder
AtomicLong在高并发下性能甚至还不如加锁,LongAdder比AtomicLong更适用于高并发下的累加TODO后续研究其原理 强引用,软引用,弱引用,幽灵引用,引用数量 强引用:StrongReference 例如Date date = new Date();...
看不到源码对象分配跟踪器 目的和范围 此代理的目的是修复过多的对象分配问题。 虽然大多数分析器确实提供了分配跟踪,但当垃圾问题真的失控时,它们都会陷入困境。 例如每秒千兆字节的对象分配。 这个单一用途的...
AtomicLong、LongAdder AtomicReference、AtomicReferenceFieldUpdater AtomicStampReference:CAS的ABA问题 原子性-synchronized 修饰代码块:大括号括起来的代码,作用于调用的对象 修饰方法:整个方法,作用于调用...
LongAdder第三周(2019/12 / 23-2019 / 12.29)同步器Java内存模型,易失性,同步,AQS,ReentrantLock,Semaphore,分布式锁第四周(2019/12 / 30-2020 / 01/05)并发集合CopyOnWriteArrayList,ConcurrentHashMap...
jmh-样本 一些 JMH - Java Microbenchmark Harness Samples 包含一些 JMH 示例代码。 地图推杆 比较 ConcurrentHashMap 与同步映射 ...比较 AtomicLong 与 LongAdder 随机基准 比较 Random 与 ThreadLocalRandom
本文主要介绍Java 高并发JDK8的支持,这里整理了详细的资料及1. LongAdder 2. CompletableFuture 3. StampedLock的介绍,有兴趣的小伙伴可以参考下