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

volatile变量同步后,线程1为何能读取非volatile变量stop的正确值?

private static boolean stop = false;
private static volatile boolean stop_volatile = false;
public static void main(String[] args) {
    Thread thread0 = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stop = true;
        stop_volatile = true;
    });

    Thread thread1 = new Thread(() -> {
        while (true) {
            if (stop_volatile){
                System.out.println("thread1:" + stop);
                break;
            }
        }
    });

    Thread thread2 = new Thread(() -> {
        while (true) {
          if (stop){
              System.out.println("thread2:" + stop);
              break;
          }
        }
    });

    thread0.start();
    thread1.start();
    thread2.start();
}

问题背景

现有两个静态字段stop和stop_volatile,其中stop_volatile被标记为volatile。thread0将两个字段的值都改为true,thread1可正常停止,thread2则无限循环。

核心疑问:

  • 为何thread1会打印“thread1:true”,它为何总能从非volatile字段stop获取正确值?
  • thread0修改stop_volatile后,会将工作缓存写入内存并通知其他线程该变量缓存失效,需重新从内存加载。但stop是非volatile变量,为何thread1未用缓存值而重新加载?

原因解析

这是volatile变量内存语义带来的连锁效果,和Java内存模型(JMM)的规则直接相关:

  1. thread0的写入顺序保证
    thread0中先执行stop = true,再执行stop_volatile = true。由于stop_volatile是volatile变量,JMM会触发store-store屏障:这个屏障会阻止普通变量的写入操作被重排序到volatile变量写入之后,同时要求所有在volatile写入前的操作(包括stop = true)必须先同步到主内存。也就是说,thread0修改stop后,会在修改stop_volatile之前就把stop的新值刷到主内存。

  2. thread1的读取触发全缓存同步
    thread1的循环一直在读取volatile变量stop_volatile,当它检测到stop_volatile变为true时,volatile读取操作会触发load-load和load-store屏障:这两个屏障会强制当前线程的工作缓存失效,所有后续变量读取都必须从主内存重新加载。此时thread1读取stop时,自然会拿到主内存里已经被thread0更新后的true值。

  3. thread2无限循环的本质
    thread2只读取普通变量stop,JMM没有强制要求它必须从主内存刷新值。JIT编译器会对这种无同步的循环做优化:把stop的值缓存到线程工作内存的寄存器中,每次循环只读取寄存器里的旧值(false),完全不会去主内存同步。所以即便thread0已经把stop改成true,thread2也感知不到,会一直循环下去。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:33:33