欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 高性能并发计数器的比较

高性能并发计数器的比较

2024/10/24 7:31:12 来源:https://blog.csdn.net/Pluto_CSND/article/details/142377931  浏览:    关键词:高性能并发计数器的比较

参考文档:https://baijiahao.baidu.com/s?id=1742540809477784106&wfr=spider&for=pc

一、常用的并发计数方法

1、synchronized

synchronized早期是一个重量级锁,因为线程竞争锁会引起操作系统用户态和内核态切换,浪费资源,效率不高。jdk1.6对 synchronized 做了性能优化,它会经历偏向锁,轻量级锁,最后才到重量级锁,性能提升显著。jdk1.7的 ConcurrentHashMap 是基于ReentrantLock的实现了锁,但在jdk1.8之后又替换成了 synchronized,籍此可见JVM团队对synchronized的信心;

2、原子更新整型 AtomicInteger、AtomicLong

JDK1.5提供了并发的Integer/Long的操作工具类 AtomicInteger、AtomicLong。AtomicLong底层是一个乐观锁,不用阻塞线程,其利用底层操作系统的CAS来保证原子性,即在一个死循环内不断执行CAS操作,直到成功。其缺陷是当并发较大时,大量线程不断CAS,存在多次的CAS操作失败,使CPU升高,效率降低。

AtomicLong value = new AtomicLong(0);
value.incrementAndGet();

3、LongAdder [单机]

在JDK8中新增了LongAdder,这是针对Long类型的数据的操作工具类。在ConcurrentHashMap中,对Map分割成多个segment,这样多个Segment的操作就可以并行执行,从而提高性能。在JDK8中,LongAdder与ConcurrentHashMap类似,将内部操作数据value分离成一个Cell数组,每个线程访问时,通过Hash等算法映射到其中一个Cell上。 计算最终的数据结果,则是各个Cell数组的累计求和。

4、Redisson分布式累加器 [分布式]

基于Redis的Redisson分布式长整型累加器(LongAdder)采用了与java.util.concurrent.atomic.LongAdder 类似的接口。通过利用客户端内置的 LongAdder 对象,为分布式环境下递增和递减操作提供了很高的性能。其性能最高比分布式 AtomicLong 对象快 10^4 倍。

RLongAddr itheimaLongAddr = redission.getLongAddr(“itheimaLongAddr”);
itheimaLongAddr.add(100);
itheimaLongAddr.increment();
itheimaLongAddr.increment();
itheimaLongAddr.sum();

基于Redis的Redisson分布式双精度浮点累加器(DoubleAdder)采用了与 java.util.concurrent.atomic.DoubleAdder 类似的接口。通过利用客户端内置的 DoubleAdder 对象,为分布式环境下递增和递减操作提供了很高的性能。其性能最高比分布式 AtomicDouble 对象快 10^4 倍。

RLongDouble itheimaDouble = redission.getLongDouble(“itheimaLongDouble”);
itheimaDouble.add(100);
itheimaDouble.increment();
itheimaDouble.increment();
itheimaDouble.sum();

二、并发计数方法性能测试

1、测试程序

    private long count = 0;@Testpublic void counterCompare() {this.counterCousum(1,   1000 * 1000);this.counterCousum(20,  1000 * 1000);this.counterCousum(40,  1000 * 1000);this.counterCousum(60,  1000 * 1000);this.counterCousum(100, 1000 * 1000);}/*** @param threadCount 线程数量* @param increTimes 每个线程自增次数*/private void counterCousum(int threadCount, int increTimes) {long start;try {System.out.println(String.format("线程数量: %s, 自增次数: %s", threadCount, increTimes));start = System.currentTimeMillis();this.synchronizedTest(threadCount, increTimes);System.out.println("Synchronized 耗时: " + (System.currentTimeMillis() - start));start = System.currentTimeMillis();this.atomicLongTest(threadCount, increTimes);System.out.println("AtomicLong 耗时: " + (System.currentTimeMillis() - start));start = System.currentTimeMillis();this.longAdderTest(threadCount, increTimes);System.out.println("LongAdder 耗时: " + (System.currentTimeMillis() - start) + "\n");} catch (Exception e) {e.printStackTrace();}}private void atomicLongTest(int threadCount, int times) throws InterruptedException {AtomicLong count = new AtomicLong();List<Thread> threadList = new ArrayList<>();for (int i = 0; i < threadCount; i++) {threadList.add(new Thread(()-> {for (int j = 0; j < times; j++) {count.incrementAndGet();}}));}for (Thread thread : threadList) {thread.start();}for (Thread thread : threadList) {thread.join();}}private void synchronizedTest(int threadCount, int times) throws InterruptedException {List<Thread> threadList = new ArrayList<>();for (int i = 0; i < threadCount; i++) {threadList.add(new Thread(()-> {for (int j = 0; j < times; j++) {add();}}));}for (Thread thread : threadList) {thread.start();}for (Thread thread : threadList) {thread.join();}}private synchronized void add() {count++;}private void longAdderTest(int threadCount, int times) throws InterruptedException {LongAdder count = new LongAdder();List<Thread> threadList = new ArrayList<>();for (int i = 0; i < threadCount; i++) {threadList.add(new Thread(()-> {for (int j = 0; j < times; j++) {count.increment();}}));}for (Thread thread : threadList) {thread.start();}for (Thread thread : threadList) {thread.join();}}

2、测试结果

在这里插入图片描述
synchronized、AtomicLong的耗时随着并发量的增大而增大,LongAdder的耗时保持相对稳定,性能优越 !!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com