之前看了java8的longadder实现,最近又看到一篇文章介绍longadder的,http://ifeve.com/atomiclong-and-longadder/
其实现思路也是分段,最后需要get的时候进行sum计算。其核心思路就是减少并发,但之前老的Atomic,难道就没有提升的空间了吗?昨晚进行了一次测试
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
publicfinalint incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
以incrementAndGet为例,在非常高的并发下,compareAndSet会很大概率失败,因此导致了此处cpu不断的自旋,对cpu资源的浪费
既然知道此地是高并发的瓶颈,有什么办法呢?
publicclass AtomicBetter {
AtomicInteger ai = new AtomicInteger();
publicint incrementAndGet() {
for (;;) {
int current = ai.get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
/**
* 如果cas失败,线程park
* @param current
* @param next
* @return
*/
privateboolean compareAndSet(int current, int next) {
if (ai.compareAndSet(current, next)) {
returntrue;
} else {
LockSupport.parkNanos(1);
returnfalse;
}
}
}
很简单,当cas失败后,对线程park,减少多线程竞争导致的频繁cas失败,更进一步的导致cpu自旋,浪费cpu的运算能力
在4核虚拟机,Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz linux 2.6.32,注意,老版本的内核,不支持高ns级的精度
下进行测试,同样都起4个线程,每个线程里面对AtomicInteger进行5kw次的incrementAndGet
原生的AtomicInteger,耗时14232ms,进行了35870次上下文切换,总共87967770955次时钟周期
那prak 1ns下呢,耗时5195ms,进行了19779次上下文切换,总共36187480878次时钟周期
明显性能上比原生的AtomicInteger更好,那这个park多少合适呢?那就只有人肉测试了
park |
time (ms) |
context-switches |
cycles |
AtomicInteger |
14232 |
35,870 |
87,967,770,955 |
1ns |
5195 |
19,779 |
36,187,480,878 |
10ns |
5050 |
20,223 |
34,839,351,263 |
100ns |
5238 |
20,724 |
37,250,431,417 |
125ns |
4536 |
47,479 |
26,149,046,788 |
140ns |
4008 |
100,022 |
18,342,728,517 |
150ns |
3864 |
110,720 |
16,146,816,453 |
200ns |
3561 |
125,694 |
11,793,941,243 |
300ns |
3456 |
127,072 |
10,200,338,988 |
500ns |
3410 |
132,163 |
9,545,542,340 |
1us |
3376 |
134,463 |
9,125,973,290 |
5us |
3383 |
122,795 |
9,009,226,315 |
10us |
3367 |
113,930 |
8,905,263,507 |
100us |
3391 |
50,925 |
8,359,532,733 |
500us |
3456 |
17,225 |
8,096,303,146 |
1ms |
3486 |
10,982 |
7,993,812,198 |
10ms |
3456 |
2,600 |
7,845,610,195 |
100ms |
3555 |
1,020 |
7,804,575,756 |
500ms |
3854 |
822 |
7,814,209,077 |
本机环境下,park 1ms下,相对耗时,cs次数来说是最好的。因此这种优化要达到最佳效果,还要看cpu的情况而定,不是一概而定的
两个问题:
<!--[if !supportLists]-->1、<!--[endif]-->cas失败对线程park的副作用是什么
<!--[if !supportLists]-->2、<!--[endif]-->如果park的时间继续加大,那会是这么样的结果呢
相关推荐
测试java.util.concurrent.atomic.AtomicInteger的类 与直接使用int做区别
NULL 博文链接:https://zcmor.iteye.com/blog/1535524
主要介绍了Java中对AtomicInteger和int值在多线程下递增操作的测试,本文得出AtomicInteger操作 与 int操作的效率大致相差在50-80倍上下的结论,需要的朋友可以参考下
主要介绍了Java AtomicInteger类的使用方法详解,文中有具体实例代码,具有一定参考价值,需要的朋友可以了解下。
AtomicInteger atomicInteger = new AtomicInteger(5); atomicInteger.compareAndSet(5, 2020) + \t current data is + atomicInteger.get()) /** * Atomically sets the value to the given updated value * if ...
AtomicInteger是java并发包下面提供的原子类,主要操作的是int类型的整型,通过调用底层Unsafe的CAS等方法实现原子操作。下面小编和大家一起学习一下
主要介绍了Java AtomicInteger类使用方法实例讲解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
利用ViewPager实现的广告轮播,没有触摸事件的时候可以定时轮播广告,有触摸事件实施触摸事件。自动轮播使用的是线程加AtomicInteger的方式实现。
AtomicInteger示例AtomicInteger用于原子增量计数器之类的应用程序。 简短的示例代码: public class AtomicIntegerExample { private final ExecutorService execService = Executors . newFixedThreadPool( 100 );...
NULL 博文链接:https://it-fan.iteye.com/blog/1183175
线程基础,线程池,生命周期
Redis数据结构与对象总结 数据结构与对象 简单动态字符串 SDS简介 SDS与C字符串的区别 常数复杂度获取字符串长度 O(n) O(1) 杜绝缓冲区溢出 修改字符串长度时内存重分配 空间预分配:对字符串进行增长操作时...
在多线程环境下,对于自增操作需要考虑线程安全问题,常见的解决方法包括使用synchronized关键字、AtomicInteger、LongAdder和LongAccumulator等。本文给出了使用这些方法实现自增的代码演示,并通过多线程测试比较...
包含了jsp的简单分页,有首页、尾页、上下页、设置页面数字等,有完整的注释、包、ppt等,mysql数据库的,对后台管理的删除有不错的参考价值,非常适合web初学者,改改就可以在多少场合运用。
用Java代码所写的简单计数器,功能:根据选票人投票,最后记录数据并用立方图显示结果
这个代码实现了一个简单的计数器,使用了Java的`AtomicInteger`类来保证多线程环境下的原子性操作。`AtomicInteger`是一个支持原子操作的整数类,它内部使用了CAS(Compare And Swap)算法来实现线程安全的操作。在...
增加对 android 版本序列化的 AtomicInteger/AtomicLong 支持 修改下划线或者相似属性重复时解析结果不对的问题 #1089 反序列化增强对非静态内嵌类的支持,提供更友好的出错信息 #1082 新增反序列化特性 Feature....
原子操作:JUC提供了一些原子操作类,如AtomicInteger、AtomicLong等,可以实现线程安全的原子操作,避免了使用synchronized关键字的性能损耗。 锁机制:JUC提供了Lock接口和Condition接口,可以实现更细粒度的锁...
volatile关键字的非原子性、volatile关键字的使用、AtomicInteger原子性操作、线程安全小例子:多个线程竞争问题、多个线程多个锁问题、创建一个缓存的线程池、多线程使用Vector或者HashTable的示例(简单线程同步...
kotlinx.atomicfu:在Kotlin中使用原子操作的惯用方式