当前位置: 首页 > news >正文

以AtomicInteger为例的Atomic 类的底层CAS细节理解

一、Atomic 类的目标

AtomicIntegerAtomicLong 等的设计目标是:

无锁(Lock-free) 的情况下,保证单个变量的原子操作。

例如:

AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();  // 原子 +1,不会有线程竞争问题

二、核心原理:CAS(Compare And Swap)

CAS 是一种原子性 CPU 指令(比如 x86 的 CMPXCHG),语义是:

“比较并交换”:如果当前值 == 期望值,则更新为新值;否则不变。

公式化描述:

boolean CAS(V, A, B)
{if (V == A)V = B;elsedo nothing;
}

参数解释:

  • V:内存中的当前值(实际值)
  • A:期望值(expected value)
  • B:要更新的新值(new value)

整个比较 + 赋值操作由 CPU 保证原子性。


三、AtomicInteger 的实现源码分析

public class AtomicInteger {private volatile int value;//表示 value 字段在对象内存中的偏移量private static final long valueOffset;// AtomicInteger类中定义public final int incrementAndGet() {// 调用Unsafe类的getAndAddInt方法,// 参数: (当前对象, value字段的内存偏移量, 增量1)// 返回值是执行前的旧值,所以最后 +1 得到新值。return unsafe.getAndAddInt(this, valueOffset, 1) + 1;}}

重点在 unsafe.getAndAddInt()

// Unsafe.java 中的方法
public final int getAndAddInt(Object obj, long offset, int delta) {int prev; // 保存当前读取到的旧值do {// 从 obj 对象的 offset 位置(也就是 value 字段)读取当前值// 使用 volatile 语义保证内存可见性prev = getIntVolatile(obj, offset);// 调用 CAS(Compare And Swap)原子操作// 比较:如果内存中该位置的值 == prev,//       就更新为 prev + delta(这里 delta = 1)// 否则说明有别的线程改动过,CAS 返回 false,进入下一次自旋重试。} while (!compareAndSwapInt(obj, offset, prev, prev + delta));// 当CAS成功(返回true)时,循环退出// 返回的是修改前的旧值return prev;
}

👉 整个过程:

  1. 读取当前值 prev
  2. 尝试用 CAS 更新为 prev + delta
  3. 如果失败(表示被其他线程改过),则 自旋重试
  4. 成功后返回旧值。

这就是 无锁自旋 + CAS 原子更新


四、为什么需要 volatile?为什么返回旧值?

1. value 字段被声明为 volatile

private volatile int value;

作用: 确保每次读取都是主内存最新值,因为 prev = getIntVolatile(obj, offset);这行代码,每次都是从对象在内存中的偏移量读取最新的旧值。
2. 关于旧值
自我理解:因为不管CAS操作成功与否,CPU指令都会将旧值写到EAX 寄存器中,而寄存器的返回速度是最快的。


五、底层实现依赖:Unsafe / VarHandle

早期(JDK8 及之前):

  • 通过 sun.misc.Unsafe.compareAndSwapInt() 实现;
  • 调用 JVM 本地方法,最终用 CPU 指令 CMPXCHG

JDK9 之后:

  • 使用更安全的 VarHandle
  • 实现方式仍是 CAS,只是封装 API 改变了。

六、CAS 的优缺点

  • 优点:自旋,不会因为第一次没拿到锁,就返回失败,业务还是有成功抢锁的几率的,提高了业务线程的成功率
  • 缺点:业务线程会长期占用CPU和内存,如果有高并发,并且如果竞争比较激烈,那么有大量的线程在自旋尝试获取锁,不是快速失败的设计。
  • CAS过度竞争后果:
    • 内存压力大;
    • CPU无效繁忙(CPU利用率虚高,不断重试)->实际任务完成少->系统吞吐量下降;
    • 和线程频繁上下文切换导致的CPU繁忙不一样,但结果是一样的->实际任务完成少->系统吞吐量下降;
优点缺点
无锁,性能高ABA 问题
不会阻塞自旋长期占用CPU和内存
不会引发线程切换只能操作一个变量
线程阻塞/切换状态切换:用户态->内核态->用户态
[用户态 T1 执行] │▼
发起阻塞 → 系统调用│▼
[内核态 T1] 保存寄存器,切换堆栈│▼
修改 T1 状态 → Blocked,调度 T2│▼
[内核态 T2] 加载寄存器,准备运行│▼
切换 T2 到用户态运行

七、典型的扩展场景

功能底层仍基于 CAS
AtomicInteger整型原子操作
AtomicLong长整型原子操作
AtomicReference对象引用更新
AtomicStampedReference解决 ABA 问题
LongAdder分段累加优化高并发✅(内部多 CAS)

八、总结一句话

Atomic 系列类底层确实基于 CAS(Compare-And-Swap)+ volatile + 自旋重试 实现原子性。
它是 CPU 原语级别的无锁同步机制,是 Java 并发包最基础的实现之一。

http://www.dtcms.com/a/488533.html

相关文章:

  • 免费网站域名注册申请同一服务器建两个wordpress
  • 中国建设银行安徽省分行网站广州icp网站测评
  • 视频压缩包加密的操作
  • 网站如何做的看起来高大上有没有可以免费的片
  • Manim作图结构基本初探
  • 长春建设公司网站搜索引擎seo推广
  • 佛山市住房建设局网站投放广告的渠道有哪些
  • VB.NET 中的常量与变量
  • 推广发帖网站去哪找wordpress主题
  • 光泽网站建设wzjseo网站交换链接怎么做?
  • 怎样做网站的后台商务网站规划与设计实训报告
  • 给文字做网站链接网站为什么续费
  • 网站推广的内容wordpress ico不显示
  • 小轲网站建设wordpress调用站点标题
  • 郑州网站建设公司哪家专业好找人做网站注意什么问题
  • 用非(~)和与()表示亦或(^)
  • 郑州网站建设索q479185700济南网络公司哪家好
  • 性能测试+监控体系一站式搭建指南:从脚本设计到服务器资源全景监控
  • 网站还难做啊手机兼职软件
  • 网站后台程序如何做读书网站建设策划书
  • 如何使用二级域名做网站毛绒玩具东莞网站建设
  • PCIe协议之 PAM4 篇之格雷码应用,你真理解了吗?(二)
  • navigation2基础-lifecycle_node 的使用
  • 中国建设银行复核网站网上商城系统软件
  • 长沙网站建设推广服务嘉兴网站制作价格
  • 曲阜做网站哪家好营销方向有哪些
  • 作业 1
  • 一个算法题 吃火锅
  • 关于网站开发的商业计划书烟台公司网站建设
  • aspcms网站使用教程平面设计周记100篇