游乐游手机版
首页/业界动态/文章详情

Atomic原子类与LongAdder源码解析:CAS无锁并发高性能原子操作基石

时间:2026-07-20 13:18
原子类基于CAS与volatile实现无锁并发,通过自旋重试保证原子性。ABA问题由AtomicStampedReference以版本号解决。高并发场景下LongAdder采用分段CAS分散竞争,大幅提升性能,适用于允许轻微误差的计数场景;AtomicLong适合低并发与强一致性需求。

今天我们来深入探讨高并发编程中一个绕不开的核心话题:原子类。无论是接口限流计数器、分布式ID生成器,还是秒杀库存扣减,底层都离不开无锁原子操作。它不仅是性能优化的基石,也是面试中高频出现的考点——CAS底层原理是什么?AtomicInteger源码如何实现?为什么高并发下LongAdder比AtomicLong快这么多?这些问题,我们将在本文中一次讲透,结合真实业务场景与性能对比,让无锁编程不再停留在理论层面。

一、先搞懂:为什么需要原子类?

先看几个最具代表性的应用场景:

  • 接口限流计数器——多线程统计QPS,请求数量不能少算;
  • 分布式ID生成器——基于原子类自增,保证ID全局唯一;
  • 秒杀库存扣减——高并发下库存既不能超卖,也不能少卖。

这些场景的共同特点是什么?多个线程同时修改同一个共享变量,且要求结果绝对准确。而普通的i++,本质上是“读-改-写”三步操作,在多线程环境下根本无法保证原子性:

// 反例:多线程下线程不安全
private int count = 0;
public void increment() {
    count++; // 实际执行:int temp = count; count = temp + 1;
}

解决方案其实只有两条路:要么使用互斥锁(synchronized/ReentrantLock),同一时间只允许一个线程操作,但代价是性能大幅下降;要么使用原子类——它基于CPU原生的CAS指令,无锁、无阻塞、轻量高效,才是高并发场景下的首选。

二、CAS核心原理:无锁编程的底层逻辑

原子类之所以能实现“无锁”,依靠的是一个叫做CAS(Compare And Swap)的CPU原子指令。所谓原子指令,就是硬件层面保证该操作不可分割。

1. 三个核心参数

  • 内存地址V:要修改的变量,例如AtomicInteger中的value;
  • 预期旧值A:线程读取到的最新值;
  • 目标新值B:想要改成什么值。

2. 执行逻辑

用伪代码表示如下:

boolean compareAndSwap(V, A, B) {
    if (V的当前值 == A) {
        V = B; // 符合预期,修改成功
        return true;
    }
    return false; // 被其他线程改过,返回失败
}

流程其实很简单:线程1读取到V=10(A=10),准备改成11(B=11)。此时它判断V当前是否还是10?如果是,就修改;如果已经被其他线程改成了别的值,那就重新读取最新值,再尝试一次——这就是所谓的“自旋”。

3. 关键提醒:CAS并非“完美无缺”

  • 优点:无锁,无线程上下文切换,低并发下性能远超锁;
  • 缺点:高并发下大量线程同时CAS同一个变量,会导致频繁的自旋重试,CPU占用率可能直线飙升。

三、AtomicInteger源码解析:最常用的原子类

以JDK8的AtomicInteger为例,核心源码其实只需关注两处,其余都是辅助逻辑。

1. 核心结构

public class AtomicInteger extends Number implements Serializable {
    private static final Unsafe unsafe = Unsafe.getUnsafe(); // JDK底层工具,直接操作内存
    private static final long valueOffset; // value的内存偏移地址
    private volatile int value; // 实际值,volatile保证可见性

    static {
        valueOffset = unsafe.objectFieldOffset(
            AtomicInteger.class.getDeclaredField("value"));
    }
}

这里有两个关键点:Unsafe提供了直接操作内存的能力;valueOffset是value字段的内存偏移量,CAS正是通过这个偏移量直接修改内存中的值。而volatile保证了所有线程都能看到value的最新值。

2. 核心方法:getAndIncrement

public final int getAndIncrement() {
    // 自旋CAS:失败则重试,直到成功
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

// Unsafe底层实现
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2); // 读取最新值
        // CAS尝试修改:预期值var5,新值var5+1;失败则循环
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}

看到这个do-while循环了吗?这就是自旋——如果CAS失败,就立刻重新读取值、再尝试,直到成功为止。在低并发场景下,一次就能成功,效率极高;但一旦竞争激烈,线程就会在这里空转消耗CPU。

四、CAS的经典问题:ABA问题 & 解决方案

1. 什么是ABA?

想象这样一个场景:线程1读取到V=A,准备改成B;这时线程2插队,先把A改成B,然后又改回A;线程1恢复执行,发现V还是A,认为没人动过,于是修改成功。这就是ABA问题。

风险主要出现在无锁链表或栈这类数据结构中:一个节点被删除后又重新插入(地址或数值相同),CAS判断“没变过”,但实际上链表结构已经改变,可能导致严重的逻辑错误。普通计数业务倒不太怕ABA,真正需要警惕的是那些依赖对象状态一致性的场景。

2. 解决方案:AtomicStampedReference

思路很简单——给变量加一个“版本号”,每次修改版本号加1。CAS操作时,不仅比较值,还要比较版本号:

// 初始化:值为100,版本号为1
AtomicStampedReference ref = new AtomicStampedReference<>(100, 1);

// 正确修改:预期值100,预期版本1,新值150,新版本2
boolean success = ref.compareAndSet(100, 150, 1, 2);

这样一来,即使值被改回了100,版本号已经变成2,CAS仍然会失败,ABA问题就被彻底堵住了。

五、高并发终极优化:LongAdder为什么比AtomicLong快?

1. AtomicLong的缺陷

高并发场景下(比如1000个线程同时计数),所有线程都去CAS竞争同一个value。结果就是大量线程自旋重试,CPU占用率飙到100%,QPS反而急剧下降——典型的“好心办坏事”。

2. LongAdder的核心思想:分段CAS

LongAdder的思路是“空间换时间”。它把原来一个变量拆成多个“分段Cell”,让线程分散到不同的Cell上竞争,最后再把所有Cell的值汇总:

  • 无竞争时:直接操作base值,节省内存;
  • 有竞争时:修改对应的Cell,减少冲突;
  • 冲突严重时:自动扩容Cell数组,进一步分散压力。

3. 核心结构

LongAdder对外只提供业务方法,核心逻辑都复用了父类Striped64

public class LongAdder extends Striped64 implements Serializable {
    public LongAdder() {}

    // 核心1:自增1
    public void increment() {
        add(1L);
    }

    // 核心2:自增指定值
    public void add(long x) {
        Cell[] as; long b, v; int m; Cell a;
        // 先尝试改base;有竞争则改对应Cell
        if ((as = cells) != null || !casBase(b = base, b + x)) {
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended = a.cas(v = a.value, v + x))) {
                // 调用父类处理竞争、初始化/扩容cells
                longAccumulate(x, null, uncontended);
            }
        }
    }

    // 核心3:sum()是弱一致性求和,过程中不加锁
    public long sum() {
        Cell[] as = cells; Cell a;
        long sum = base;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null)
                    sum += a.value;
            }
        }
        return sum;
    }
}

注意sum()方法——它在求和过程中不加锁,高并发下只能拿到近似值。所以如果需要强一致性的计数(比如金融交易),就不要用LongAdder了。

4. AtomicLong vs LongAdder 对比表

(说明:原文此处有对比表格,但输出中无法完整呈现,核心差异概括为:低并发/需要强一致/需要get/set/compareAndSet选AtomicLong;高并发计数/允许轻微误差选LongAdder,性能可提升10倍以上。)

六、实战避坑 & 选型指南

1. 坑1:volatile + 普通运算 ≠ 原子性

// 反例:线程不安全
volatile int count = 0;
count++; // 仍是读-改-写三步,多线程下会错乱

// 正解:用AtomicInteger
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();

volatile只保证可见性和禁止指令重排序,不保证原子性。这一点容易混淆。

2. 坑2:原子类只保证单次操作原子

如果业务逻辑需要“先判断再修改”,两次原子方法调用之间仍然可能被打断:

// 反例:线程不安全(两次原子操作之间可能被打断)
if (count.get() < 10) {
    count.incrementAndGet();
}

// 正解:加锁或用compareAndSet自旋
while (true) {
    int curr = count.get();
    if (curr >= 10) break;
    if (count.compareAndSet(curr, curr + 1)) break;
}

3. 坑3:高并发下盲目用AtomicLong

秒杀、高QPS统计这类场景,直接用LongAdder,性能差距可能是一个数量级。

七、核心总结

  • 原子类基于「CAS + volatile」实现无锁原子操作,低并发下性能远超锁;
  • CAS的ABA问题用AtomicStampedReference(版本号)解决;
  • 高并发计数选LongAdder(分段CAS),适合统计、监控、QPS、限流等允许轻微误差的场景;
  • 低并发、需要强一致、需要get/set/compareAndSet,选AtomicLong,更省内存;
  • volatile只保证可见性、禁止重排序,不保证原子性。
来源:https://www.51cto.com/article/840677.html
上一篇长城汽车遭遇丰田式转型阵痛 下一篇Codex隐藏功能详解与实用技巧
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
京东数码影音暑假装备投影仪游戏掌机AI眼镜一站购齐
业界动态 · 2026-07-20

京东数码影音暑假装备投影仪游戏掌机AI眼镜一站购齐

京东“数码放暑价”好物榜汇聚投影仪、游戏掌机、智能眼镜等多款全品类数码好物,提供国家补贴、以旧换新最低五折优惠,覆盖宅家观影、游戏对战、出行记录等暑期场景,全方位满足多场景趣玩需求。

年7月出差笔记本横评:五款轻薄本选购指南
业界动态 · 2026-07-20

年7月出差笔记本横评:五款轻薄本选购指南

二零二六年出差轻薄本选购指南,从便携、续航、性能等八维度评测五款机型。入门级推荐华硕无畏14SE性价比高,荣耀X14均衡;中端惠普战X均衡全面,适合商务;高端联想小新Pro16GT性能最强,适合重度应用;ThinkPadX1Carbon极致轻便,适合频繁出差。

日本人体冰箱5分钟快速降温售价约150万日元
业界动态 · 2026-07-20

日本人体冰箱5分钟快速降温售价约150万日元

日本推出“人体冰箱”DoHiemonBox,外形类似自动售货机,站立式结构,底部带滚轮。内部维持15℃环境,5℃冷风吹向头颈肩背,约5分钟快速降温,10分钟缓解不适。三种制冷模式,20分钟自动关闭,耗电仅为普通立式空调一半,主要面向高温作业人员及公共场所。

小米米家智能茶吧机Pro立式众筹价1099元
业界动态 · 2026-07-20

小米米家智能茶吧机Pro立式众筹价1099元

小米米家智能茶吧机Pro立式版众筹价1099元,集即热、煮茶、消毒于一体。配备2 8英寸触控屏及小爱同学语音控制,5 5升水箱双区双出水,15秒烧开、3秒即热。10升消毒存储空间支持UVC紫外线杀菌和PTC热风烘干,附赠茶壶与分享壶。

年7月设计本选购 五款高色准创作本深度解析
业界动态 · 2026-07-20

年7月设计本选购 五款高色准创作本深度解析

2026年设计专业笔记本选购指南推荐五款:入门华硕无畏16SE、中端惠普战X、高端YOGAAir14与ThinkPadT14p、旗舰联想小新Pro16GT。核心要点为屏幕色准、PantherLake平台AI算力及扩展性,覆盖5000至20000元以上预算。