温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

为何volatile不保证原子性

发布时间:2026-10-29 13:45:03 来源:亿速云 阅读:96 作者:小樊 栏目:编程语言

volatile 是 Java 中用于保证可见性和禁止指令重排序的关键字,但不保证原子性。下面从原理层面解释为什么会这样。


一、volatile 能保证什么?

1️⃣ 可见性

当一个线程修改了 volatile 变量,其他线程立即可见。

原理:

  • 写 volatile 变量会:
    • 强制把工作内存中的值刷回主内存
    • 使其他 CPU 缓存行失效
  • 读 volatile 变量会:
    • 直接从主内存读取

✅ 解决的是:一个线程改了,别的线程能看到


2️⃣ 有序性(禁止指令重排)

  • 写 volatile 前的操作,不会被重排到写之后
  • 读 volatile 后的操作,不会被重排到读之前

✅ 解决的是:多线程下的执行顺序问题


二、为什么 volatile 不保证原子性?

核心原因:volatile 只保证“单次读/写”的可见性,不保证“复合操作”的原子性


经典反例:i++

volatile int i = 0;

i++;

表面上是一行代码,实际是三步操作:

  1. 读取 i(从主内存)
  2. 计算 i + 1
  3. 写回 i

线程竞争场景

假设 i = 0:

时间 线程 A 线程 B
T1 读 i = 0
T2 读 i = 0
T3 计算 0+1 计算 0+1
T4 写 i = 1 写 i = 1

最终结果:i = 1(而不是 2)

❌ 虽然每次写都可见,但读—改—写不是原子的


三、volatile 的原子性边界

✅ volatile 保证原子性的情况

  • 对 基本类型的单次读或写
volatile boolean flag = true;
flag = false;  // 原子

❌ volatile 不保证原子性的情况

  • 复合操作:
    • i++
    • i += n
    • check-then-act(先判断再修改)

四、如何真正保证原子性?

1️⃣ 使用 synchronized

synchronized (this) {
    i++;
}

2️⃣ 使用原子类(推荐)

AtomicInteger i = new AtomicInteger(0);
i.incrementAndGet();

底层使用 CAS(Compare And Swap),无锁且高效。


五、一句话总结

volatile 解决“看得见”,不解决“一起做”

  • ✅ 可见性
  • ✅ 有序性
  • ❌ 原子性

如果你愿意,我也可以从 JMM(Java 内存模型) 或 CPU 缓存一致性协议(MESI) 的角度再深入讲一层。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手