Skip to content

介绍

Java不同并发场景下LongAdder和AtomicLong如何使用以及Atomic的核心原理CAS(Compare-And-Swap)机制

1.什么是原子操作?

原子操作是指操作在执行过程中不可被中断,要么全部执行成功,要么全部失败。

2.为什么需要 Atomic 类?

传统方式的局限性:

使用synchronized或ReentrantLock确保线程安全,但代价是性能的下降。

Atomic类的优势:

通过CAS实现非阻塞操作,性能更高。

3.高并发下LongAdder比AtomicLong效率高,本质是空间换时间

LongAdder是JDK8新增的类。

高并发下LongAdder比AtomicLong效率高,其本质是空间换时间。 在竞争激烈的时候,LongAdder把不同线程对应到不同的Cell上进行修改,降低了冲突的概率,是多段锁的理念,提高了并发性。

AtomicLong中有个内部变量value保存着实际的long值,所有的操作都是针对该变量进行。也就是说,高并发环境下,value变量其实是一个热点,也就是N个线程竞争一个热点。由于竞争很激烈,每一次操作,都要flush和refresh,导致很多资源浪费。

LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。如果要获取真正的long值,只要将各个槽中的变量值累加返回。但在统计的时候,如果有并发更新,可能会导致统计的数据有些误差。

4.线程竞争很低或需要准确的数值,使用AtomicLong

在线程竞争很低的情况下进行计数,使用AtomicLong还是更简单,更直接一些,并且效率会稍微高一点点。

其他的情况下,比如序列号生成啦,这种情况下需要准确的数值。 全局唯一的AtomicLong才是正确的选择

5.Atomic的核心原理CAS(compareAndSwap)

ts
public final int getAndAddInt(Object var1, Long var2, int var4){
    int var5;
    do{
      var5 = this.getIntVolatile(var1, var2);
    }while(!this.compareAndSwapInt(var1, var2, var5,var5 + var4));

    return var5;
}
/**
 * var1 传入的对象(count对象)
 * var2 加数
 * var5 底层的加数
 * var5 + var4 底层的加数 + 增加量
 */

对于当前var1(count)对象,如果当前值var2,与底层值var5相同,那么把它更新成后面的值。 因为当执行更新操作时,可能会被其他线程修改,所以需要判断。

上次更新于: