You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原子性是否保证可见性?Java中非long/double变量的可见性疑问

原子性不代表可见性:Java中非volatile原子变量的并发误区

直接给结论:原子操作和可见性是Java并发模型里完全独立的两个概念,int这类非long/double变量的原子读写,完全不保证其他线程能看到最新值。

为什么原子性和可见性没关系?

  • 原子性解决的是「操作会不会被拆分」的问题:比如int变量的读写,JVM保证这个操作是一次性完成的,不会出现线程读到一半修改后的值(比如从0改成1,不会读到0和1之间的中间值)。但这只保证操作本身的完整性,和数据的传播范围无关。
  • 可见性解决的是「线程间数据同步」的问题:没有volatile修饰时,JVM允许每个线程把变量缓存到自己的工作内存(比如CPU寄存器、本地缓存)里。线程A修改变量后,这个新值可能只存在于A的工作内存,还没同步到主内存;线程B读取时,还是从自己的工作内存拿缓存的旧值,自然看不到A的修改。

举个实际场景的例子

假设你有这样一段代码:

private int flag = 0;

// 线程A执行
public void setFlag() {
    flag = 1;
}

// 线程B执行
public void waitForFlag() {
    while (flag == 0) {
        // 空循环等待
    }
    System.out.println("Flag updated!");
}

没有volatile修饰flag的话,线程B可能会无限循环下去——因为JIT编译器可能把flag == 0的判断优化成直接读取寄存器里的旧值,根本不会去主内存重新读取最新的修改。

volatile到底起了什么作用?

对int这类变量来说,volatile的核心作用不是保证原子性(本来就有),而是:

  • 强制线程读写变量时直接操作主内存,跳过工作内存的缓存;
  • 禁止指令重排序,确保变量的修改顺序对其他线程是可见的。

什么时候需要加volatile?

只要你的变量会被多个线程共享,并且至少有一个线程会修改它,同时其他线程需要及时看到这个修改,那不管它是不是原子类型,都得加volatile。如果只是单线程操作,或者不需要实时同步修改结果,那可以不用。

内容的提问来源于stack exchange,提问作者mkarmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:01:39