• 更快的原子类:LongAdder
     大家对AtomicInteger的基本实现机制应该比较了解,它们是在一个死循环内,不断尝试修改目标值,知道修改成功,如果竞争不激烈,那么修改成功的概率就很高,否则,修改失败的概率就很高,在大量修改失败时,这些原子操作就会进行多次循环尝试,因此性能就会受到影响
     那么竞争激烈的时候,我们应该如何进一步提高系统性能呢?一种基本方案就是可以使用热点分离,将竞争的数据进行分解.基于这个思路,打击应该可以想到一种对传统AtomicInteger等原子类的改进方法,虽然在CAS操作中没有锁,但是像减少锁粒度这种分离热点的思路依然可以使用,一种可行的方案就是仿造ConcurrengHashMap,将热点数据分离,比如,可以将AtomicInteger的内部核心数据value分离成一个数组,每个线程访问时,通过哈希等算法映射到其中一个数字进行计数,而最终的计数结果,则为这个数组的求和累加,其中,热点数据value被分离成多个单元cell,每个cell独自维护内部的值,当前对象的实际值由所有的cell累计合成,这样,热点就进行了有效的分离,提高了并行度,LongAdder正是使用了这种思想.
  • 测试LongAdder,原子类以及同步锁性能测试
  1. public class LongAdderDemo {
  2. private static final int MAX_THREADS = 3;
  3. private static final int TASK_COUNT = 3;
  4. private static final int TARGET_COUNT = 10000000;
  5.  
  6. private AtomicLong acount = new AtomicLong(0L);
  7. private LongAdder lacount = new LongAdder();
  8. private long count = 0;
  9.  
  10. private static CountDownLatch cdlsync = new CountDownLatch(TASK_COUNT);
  11. private static CountDownLatch cdlatomic = new CountDownLatch(TASK_COUNT);
  12. private static CountDownLatch cdladdr = new CountDownLatch(TASK_COUNT);
  13.  
  14. protected synchronized long inc() {
  15. return ++count;
  16. }
  17.  
  18. protected synchronized long getCount() {
  19. return count;
  20. }
  21.  
  22. public class SyncThread implements Runnable {
  23. protected String name;
  24. protected long starttime;
  25. LongAdderDemo out;
  26.  
  27. public SyncThread(long starttime, LongAdderDemo out) {
  28. this.starttime = starttime;
  29. this.out = out;
  30. }
  31.  
  32. @Override
  33. public void run() {
  34. long v = out.getCount();
  35. while (v < TARGET_COUNT) {
  36. v = out.inc();
  37. }
  38. long endtime = System.currentTimeMillis();
  39. System.out.println("SyncThread spend:" + (endtime - starttime) + "ms" + " v" + v);
  40. cdlsync.countDown();
  41. }
  42. }
  43.  
  44. public void testSync() throws InterruptedException {
  45. ExecutorService exe = Executors.newFixedThreadPool(MAX_THREADS);
  46. long starttime = System.currentTimeMillis();
  47. SyncThread sync = new SyncThread(starttime, this);
  48. for (int i = 0; i < TASK_COUNT; i++) {
  49. exe.submit(sync);
  50. }
  51. cdlsync.await();
  52. exe.shutdown();
  53. }
  54.  
  55. public class AtomicThread implements Runnable {
  56. protected String name;
  57. protected long starttime;
  58.  
  59. public AtomicThread(long starttime) {
  60. this.starttime = starttime;
  61. }
  62.  
  63. @Override
  64. public void run() {
  65. long v = acount.get();
  66. while (v < TARGET_COUNT) {
  67. v = acount.incrementAndGet();
  68. }
  69. long endtime = System.currentTimeMillis();
  70. System.out.println("AtomicThread spend:" + (endtime - starttime) + "ms" + " v" + v);
  71. cdlatomic.countDown();
  72. }
  73. }
  74.  
  75. public void testAtomic() throws InterruptedException {
  76. ExecutorService exe = Executors.newFixedThreadPool(MAX_THREADS);
  77. long starttime = System.currentTimeMillis();
  78. AtomicThread atomic = new AtomicThread(starttime);
  79. for (int i = 0; i < TASK_COUNT; i++) {
  80. exe.submit(atomic);
  81. }
  82. cdlatomic.await();
  83. exe.shutdown();
  84. }
  85.  
  86. public class LongAdderThread implements Runnable {
  87. protected String name;
  88. protected long starttime;
  89.  
  90. public LongAdderThread(long starttime) {
  91. this.starttime = starttime;
  92. }
  93.  
  94. @Override
  95. public void run() {
  96. long v = lacount.sum();
  97. while (v < TARGET_COUNT) {
  98. lacount.increment();
  99. v = lacount.sum();
  100. }
  101. long endtime = System.currentTimeMillis();
  102. System.out.println("LongAdderThread spend:" + (endtime - starttime) + "ms" + " v" + v);
  103. cdladdr.countDown();
  104. }
  105.  
  106. }
  107.  
  108. public void testLongAdder() throws InterruptedException {
  109. ExecutorService exe = Executors.newFixedThreadPool(MAX_THREADS);
  110. long starttime = System.currentTimeMillis();
  111. LongAdderThread atomic = new LongAdderThread(starttime);
  112. for (int i = 0; i < TASK_COUNT; i++) {
  113. exe.submit(atomic);
  114. }
  115. cdladdr.await();
  116. exe.shutdown();
  117. }
  118.  
  119. public static void main(String[] args) throws InterruptedException {
  120. LongAdderDemo demo = new LongAdderDemo();
  121. demo.testSync();
  122. demo.testAtomic();
  123. demo.testLongAdder();
  124. }
  125. }
 
     

Java8 更快的原子类:LongAdder(笔记)的更多相关文章

  1. J.U.C体系进阶(三)- juc-atomic 原子类框架

    Java - J.U.C体系进阶 作者:Kerwin 邮箱:806857264@qq.com 说到做到,就是我的忍道! juc-atomic 原子类框架 AtomicInteger AtomicInt ...

  2. Android并发编程 原子类与并发容器

    在Android开发的漫漫长途上的一点感想和记录,如果能给各位看官带来一丝启发或者帮助,那真是极好的. 前言 上一篇博文中,主要说了些线程以及锁的东西,我们大多数的并发开发需求,基本上可以用synch ...

  3. JUC之原子类

    在分析原子类之前,先来了解CAS操作 CAS CAS,compare and swap的缩写,中文翻译成比较并交换. CAS 操作包含三个操作数 —— 内存位置(V).预期原值(A)和新值(B).如果 ...

  4. 死磕 java原子类之终结篇(面试题)

    概览 原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换. 原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割 ...

  5. JUC源码学习笔记4——原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法

    JUC源码学习笔记4--原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法 volatile的原理和内存屏障参考<Java并发编程的艺术> 原子类源码基于JDK8 ...

  6. 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理

    (1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...

  7. JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

    JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...

  8. Dnsmasq安装与配置-搭建本地DNS服务器 更干净更快无广告DNS解析

    默认的情况下,我们平时上网用的本地DNS服务器都是使用电信或者联通的,但是这样也导致了不少的问题,首当其冲的就是上网时经常莫名地弹出广告,或者莫名的流量被消耗掉导致网速变慢.其次是部分网站域名不能正常 ...

  9. Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。

    精彩理解:  https://www.jianshu.com/p/21be831e851e ;  https://blog.csdn.net/heyutao007/article/details/19 ...

随机推荐

  1. [ Linux 命令 ] grep

    一.grep是什么? Linux grep命令是用于查找文件里符合条件行的shell命令. 二.为什么要使用grep? 在查找文件内容时候,通过使用grep指定条件,可以快速定位到文件里字符串所在的行 ...

  2. 【 Keepalived 】Nginx or Http 主-主模式

    上一篇:[ Keepalived ]Nginx or Http 主-备模式 在此基础上进行修改并实现 Keepalived主-主模式 首先,需要理解的是:主-备模式是一个VIP在工作,主-主模式则需要 ...

  3. js处理富文本编辑器转义、去除转义、去除HTML标签

    富文本编辑器生成的HTML标签,进行转义,然后写入数据库,防止脚本注入: function htmlEncode(value){ return $('<div/>').text(value ...

  4. activemq修改admin密码

    vim /usr/local/activemq/conf/jetty-realm.properties 用户名:密码,角色 mq: 123, admin 那么打开管理后台,用户是mq,密码是123,具 ...

  5. 让IE6/IE7/IE8支持CSS3属性的8种方法介绍

    我们都知道,IE浏览器暂不支持CSS3的一些属性.国外的工程师们,不安于此现状,他们总是尽量使用一些手段使IE浏览器也能支持CSS3属性,我觉得这些都是很有意义,很有价值的工作,可以推动整个技术领域的 ...

  6. Python爬链接

    # -*- coding: utf-8 -*- """ Created on Wed Jan 11 17:21:54 2017 @author: PE-Monitor & ...

  7. SDL安装小结

    SDL是一个基于C的简易实现,安装过程中也多亏了,各位大神的助攻,这里简单mark一下遇到的问题,以备查找: 关于VS的版本:目前文档里确定支持的VS为2008到2013,我的VS是2013,2015 ...

  8. NOIP2010关押罪犯

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...

  9. 【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ

    枚举每个位置,给每个串的前半部分一个哈希值,后半部分一个哈希值,若是它们均相等,则视为这两个串相似. 每次转移之后,排序一下就行了. O(L*n*log(n)). #include<cstdio ...

  10. 使用shell生成随机数

    #!/bin/bash $` do $` do s=$(($RANDOM%)) done done 第1行:#!/bin/bash是指此脚本使用/bin/bash来解释执行.其中,#!是一个特殊的表示 ...