LongAdder

AmoticLong

AtomicLong是作用是对长整形进行原子操作

原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束

在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。

构造方法
AtomicLong()
创建一个新的AtomicLong,初始值为 0 。
AtomicLong(long initialValue)
用给定的初始值创建一个新的AtomicLong。  long accumulateAndGet(long x, LongBinaryOperator accumulatorFunction)
使用将给定函数应用于当前值和给定值的结果原子更新当前值,返回更新后的值。
long addAndGet(long delta)
将给定的值原子地添加到当前值。
boolean compareAndSet(long expect, long update)
如果当前值为 == ,则将原值设置为给定的更新值。
long decrementAndGet()
原子减1当前值。
double doubleValue()
返回此值 AtomicLong为 double一个宽元转换后。
float floatValue()
返回此值 AtomicLong为 float一个宽元转换后。
long get()
获取当前值。
long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction)
使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值。
long getAndAdd(long delta)
将给定的值原子地添加到当前值。
long getAndDecrement()
原子减1当前值。
long getAndIncrement()
原子上增加一个当前值。
long getAndSet(long newValue)
将原子设置为给定值并返回旧值。
long getAndUpdate(LongUnaryOperator updateFunction)
用应用给定函数的结果原子更新当前值,返回上一个值。
long incrementAndGet()
原子上增加一个当前值。
int intValue()
返回此的值 AtomicLong作为 int的基本收缩转换之后。
void lazySet(long newValue)
最终设定为给定值。
long longValue()
将 AtomicLong的值作为 long 。
void set(long newValue)
设置为给定值。
String toString()
返回当前值的String表示形式。
long updateAndGet(LongUnaryOperator updateFunction)
使用给定函数的结果原子更新当前值,返回更新的值。
boolean weakCompareAndSet(long expect, long update)
如果当前值为 == ,则将原值设置为给定的更新值。  

1.计数功能:(实现在并发环境下是不安全的 结果与期望值不一致)

    private static int count =0;public static void main(String[] args) throws Exception {List<Thread> tList =  new ArrayList<>();for (int i = 0; i <1000; i++) {new Thread(()->{ count++;}).start();}Thread.sleep(1000);//确保线程都结束System.out.println(count);/*result:996*/}

volatile

2.加volatile(结论: volatile关键字并不能作为线程计数器

    private static volatile int count =0;public static void main(String[] args) throws Exception {List<Thread> tList =  new ArrayList<>();for (int i = 0; i <1000; i++) {new Thread(()->{ count++;}).start();}Thread.sleep(1000);//确保线程都结束System.out.println(count);/*result:991*/}

原因:在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,

线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存

变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,

在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图

描述这写交互

read and load 从主存复制变量到当前工作内存
use and assign 执行代码,改变共享变量值
store and write 用工作内存数据刷新主存相关内容

其中use and assign 可以多次出现

但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样

对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的

例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值

在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6

线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6

导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。

转载于:https://www.cnblogs.com/jianwei-dai/p/6246067.html

synchronized

  1. 使用synchronized(结果正确)

        private static int count =0;public static void main(String[] args) throws Exception {List<Thread> tList =  new ArrayList<>();for (int i = 0; i <1000; i++) {new Thread(()->{synchronized (ThreadTest1.class){count++;}}).start();}Thread.sleep(1000);//确保线程都结束System.out.println(count);/*result:1000*/}
    

    问题:Synchronized悲观锁,是独占的,意味着如果有别的线程在执行,当前线程只能是等待!

    JDK1.5以后这种轻量级的解决方案不再推荐使用synchronized,而使用Atomic代替,因为效率更高

    AotmicInteger其实就是对int的包装,然后里面内部使用CAS算法来保证操作的原子性

    public final int incrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
    可以看到,内部主要依赖于unsafe提供的CAS算法来实现的
    

AmoticLong

  1. 用AmoticLong

        private static AtomicLong count = new AtomicLong(0);public static void main(String[] args) throws Exception {List<Thread> tList =  new ArrayList<>();for (int i = 0; i <1000; i++) {new Thread(()->{count.incrementAndGet();}).start();}Thread.sleep(1000);//确保线程都结束System.out.println(count.get());/*result:1000*/}
    

    问题:

    AtomicLong的实现方式是CAS.

    CAS机制就是,在一个死循环内,不断尝试修改目标值,直到修改成功。如果竞争不激烈,那么修改成功的概率就很高,否则,修改失败的的概率就很高,在大量修改失败时,这些原子操作就会进行多次循环尝试,因此性能就会受到影响

longAdder

将AtomicInteger的内部核心数据value分离成一个数组,每个线程访问时,通过哈希等算法映射到其中一个数字进行计数,而最终的计数结果,则为这个数组的求和累加。热点数据value被分离成多个单元cell,每个cell独自维护内部的值,当前对象的实际值由所有的cell累计合成,这样热点就进行了有效的分离,提高了并行度。

    static LongAdder count = new LongAdder();public static void main(String[] args) throws Exception {List<Thread> tList =  new ArrayList<>();for (int i = 0; i <1000; i++) {new Thread(()->{count.add(1);}).start();}Thread.sleep(1000);//确保线程都结束System.out.println(count.longValue());/*result:1000*/}

LongAdder和AmoticLong性能测试

public static void main(String[] args) throws Exception {test(1);test(10);test(20);test(40);test(100);}static  void test(int threadCount) throws Exception{System.out.print("threadCount:" + threadCount+"    ");Long startTime = System.currentTimeMillis();testLongAdder(threadCount) ;System.out.print("LongAdder run time :" + (System.currentTimeMillis() - startTime)+"       ");Long startTime2 = System.currentTimeMillis();testAmoticLong(threadCount) ;System.out.println("AmoticLong run time :" + (System.currentTimeMillis() - startTime2));/*threadCount:1    LongAdder run time :131       AmoticLong run time :55threadCount:10    LongAdder run time :192       AmoticLong run time :2060threadCount:20    LongAdder run time :332       AmoticLong run time :4081threadCount:40    LongAdder run time :779       AmoticLong run time :6876threadCount:100    LongAdder run time :1627       AmoticLong run time :20495*/}static LongAdder count = null;static void testLongAdder(int threadCount) throws Exception{count = new LongAdder();List<Thread> list = new ArrayList<>();for (int i = 0; i <threadCount; i++) {Thread t= new Thread(()->{for (int j = 0; j < 10000000; j++) {count.add(1);}});list.add(t);}for(Thread t:list){t.start();}for(Thread t:list){t.join();}}private static AtomicLong countAmotic = null;static void testAmoticLong(int threadCount) throws Exception{countAmotic =  new AtomicLong(0);List<Thread> list = new ArrayList<>();for (int i = 0; i <threadCount; i++) {Thread t= new Thread(()->{for (int j = 0; j < 10000000; j++) {countAmotic.incrementAndGet();}});list.add(t);}for(Thread t:list){t.start();}for(Thread t:list){t.join();}}

结论:AtomicLong在线程数量低的时候 性能和LongAdder相近,优于LongAdder,但是线程数量多了 性能明显低于LongAdder,

            countAmotic.incrementAndGet();}});list.add(t);}for(Thread t:list){t.start();}for(Thread t:list){t.join();}
}

结论:AtomicLong在线程数量低的时候 性能和LongAdder相近,优于LongAdder,但是线程数量多了 性能明显低于LongAdder,​   所以 **用LongAdder替代AtomicLong**

LongAdder和AtomicLong相关推荐

  1. 性能优化之使用LongAdder替换AtomicLong

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://juejin.cn/post/6921595303460241415 写在前面 本篇文章并不会直接进入主题讲为 ...

  2. [JDK8]性能优化之使用LongAdder替换AtomicLong

    如果让你实现一个计数器,有点经验的同学可以很快的想到使用AtomicInteger或者AtomicLong进行简单的封装. 因为计数器操作涉及到内存的可见性和线程之间的竞争,而Atomic***的实现 ...

  3. Java中的LongAdder和AtomicLong有什么区别?

    ● Java中的LongAdder和AtomicLong有什么区别? 考点:JDK 参考回答: JDK1.8引入了LongAdder类.CAS机制就是,在一个死循环内,不断尝试修改目标值,直到修改成功 ...

  4. LongAdder和AtomicLong哪个性能更好,为什么?

    点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/limenghua9112/ article/details/107950744 概述 AtomicLong是作者Doug Le ...

  5. 【078期】java.util.* 并发包下 LongAdder 和 AtomicLong 哪个性能更好,为什么?

    点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方留言必回,有问必答! 每天 08:00 更新文章,每天进步一点点... 概述 ...

  6. LongAdder 和 AtomicLong

    有幸看到一篇关于这个讲解 2个类的讲解,自己也归纳总结一下. 一.解析 看源码底层会发现实现机制不一样,当然这个也是必须的 LongAdder 点进去之后会发现,CAS 它是一个CAS的实现类.至于C ...

  7. LongAdder及AtomicLong

    AtomicLong原理   就像我们所知道的那样,AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目 ...

  8. AtomicLong和LongAdder的区别

    转载自 https://blog.csdn.net/yao123long/article/details/63683991 前言   最近在看到不少框架里面使用到了LongAdder这个类,而并非At ...

  9. 线程安全之原子性Atomic(AtomicInteger|LongAdder|AtomicLong)

    线程安全性 当多线程访问某个类时,不管运行环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何的同步或者协同,这个类都能表现出正确的行为,那么这个类就是线程安全的. 原子性 提供 ...

最新文章

  1. IDEA 连接MySQL数据库
  2. 艾伟也谈项目管理,谈谈如何说“不”
  3. 如何在两个目录中删除其中一个目录中同名文件
  4. 自定义实现ProgressDialog样式的Dialog
  5. OS-鸿蒙系统-以及编译器
  6. 基于tensorflow2.0利用CNN与线性回归两种方法实现手写数字识别
  7. 中国大学MOOC-陈越、何钦铭-数据结构-2019春期末考试(题目+部分解答)
  8. 爱奇艺怎么开启从列表删除时同时删除本地文件
  9. 样式中指定调用的效果
  10. java(14) - HashMap类
  11. Delphi版 熊猫烧香源码
  12. 免费的中医处方系统软件
  13. netapp linux ntfs,netapp存储常用命令
  14. 2018-08-14 UnmarshalException: 意外的元素 (uri:, local:customer)
  15. excel高级筛选怎么用_神!Excel高级筛选原来如此好用
  16. IDEA中HTML代码格式化问题
  17. java项目生成多个条码_java – 生成随机条形码 – 一个设计问题
  18. 拥抱520,感性去爱,理性成长
  19. 耗时3个多月、总结过往5年,马毅曹颖沈向洋撰文智能两大原则
  20. 海康威视web插件【浏览器部分兼容 全兼容】

热门文章

  1. sklearn 笔记 TSNE
  2. 淘宝开店第四天应该多少订单?淘宝订单数量如何提升?
  3. 公元前后的王莽与屋大维
  4. 华为Hybrid接口详解(原理+配置)
  5. 实现 JSON + Jquery+.Net ajax功能
  6. 猫和老鼠手游怎么才能快速上分?目前胜率已经超过90%
  7. 两种方法删除NSUserDefaults所有记录
  8. 牛客网题库分享--final byte
  9. SS626V100 SDK安装编译osdrv问题汇总
  10. 《Exploring in UE4》Unreal回放系统剖析(上)