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

无法理解线程行为:读写线程注释println后无输出的问题

多线程静态变量读取的缓存一致性问题分析

问题代码

package safety.publishing;

public class PublicStaticPublishing {

    public static void main(String[] args) {
        new Thread(new ReadRunnable()).start();
        new Thread(new WriteRunnable()).start();
    }

}

class A {
    public static int i = 0;
}

class ReadRunnable implements Runnable {
    int cache = A.i;
    @Override
    public void run() {
        for (;;) {
            if (A.i != cache) {
                System.out.println("cache miss " + A.i + " " + cache);
                cache = A.i;
            } else {
                // System.out.println("cache hit"); 
            }
        }
    }
}

class WriteRunnable implements Runnable {
    @Override
    public void run() {
        for (int i =0; i<1000; i++) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
            A.i++;
        }
    }
}

现象描述

当前代码包含一个读线程和一个写线程,出现两种截然不同的运行结果:

  • 注释掉else块的System.out.println("cache hit");时,if块的输出完全不执行,控制台持续空白;
  • 取消注释后,if和else块的输出都正常执行,示例输出如下:
cache hit
cache hit
cache hit
cache hit
cache hit
cache hit
cache hit
cache hit
cache hit
cache hit
cache miss 222 221
cache hit

原理分析

核心问题出在Java内存模型(JMM)的缓存可见性和JIT即时编译器的优化上:

  1. 无else输出时的JIT优化
    读线程的循环逻辑里没有任何同步机制触发内存刷新。JIT编译器会判定A.i的值不会被其他线程修改,进而做循环不变量优化:把A.i的读取缓存到线程本地的寄存器或栈中,后续循环不再去主内存读取最新值。这就导致读线程永远看不到写线程对A.i的修改,if条件永远不成立,自然没有输出。

  2. 有else输出时的内存屏障
    System.out.println()方法内部包含synchronized同步块。根据JMM规则:

    • 退出synchronized块时,线程会把本地缓存的变量刷新到主内存;
    • 进入synchronized块时,线程会失效本地缓存,强制从主内存重新读取变量。
      这相当于给读线程加了隐性的内存屏障,保证每次循环都能获取到A.i的最新值,所以能正常检测到变量变化,输出cache hit和cache miss。

解决方案

解决这类多线程可见性问题,有两种常用方式:

  • 给A.i添加volatile关键字:
    class A {
        public static volatile int i = 0;
    }
    
    volatile会禁止JIT的缓存优化,保证每次读取A.i都直接从主内存获取,写入时立即刷新到主内存,强制多线程间的变量可见性。
  • 使用同步锁包裹A.i的读写操作,比如在读取和修改A.i时加synchronized块,同样能触发内存屏障,保证可见性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:17:27