贝利信息

在Java中内存可见性是什么意思_Java并发核心概念解析

日期:2026-01-25 00:00 / 作者:P粉602998670
内存可见性指线程对共享变量的修改能否被其他线程及时看到,因JMM中线程操作变量需经工作内存与主内存间复制,无同步时修改可能不及时刷回主内存;volatile通过强制读写主内存及禁止重排序解决该问题,但不保证原子性;synchronized也保证可见性,但以加锁和更大开销为代价,提供原子性保障。

内存可见性,指的是一个线程对共享变量的修改,能被其他线程“及时看到”。它不是“会不会被看到”,而是“什么时候被看到”——不加同步时,flag = true 执行完,另一个线程仍可能永远读到 false

为什么改了值,另一个线程却读不到?

Java 内存模型(JMM)把内存分成两层:主内存(所有线程共享)和每个线程私有的工作内存。线程操作变量时,并不直接读写主内存,而是:

问题就出在第三步:没有同步机制时,JIT 编译器或 CPU 缓存可能让线程一直用自己工作内存里的旧值,根本不查主内存。比如下面这段代码会死循环:

public class VisibilityDemo {
    static boolean run = true;

    pub

lic static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { while (run) { } // 空循环 System.out.println("退出"); }); t.start(); Thread.sleep(100); run = false; // 主线程改了,但 t 线程看不到 } }

volatile 是怎么解决可见性的?

volatile 不是锁,但它强制两点:

只需把上面的 static boolean run = true 改成 static volatile boolean run = true,问题就消失。但注意:volatile 只保可见性和有序性,不保原子性——count++ 这种复合操作仍需 synchronizedAtomicInteger

synchronized 也能解决可见性,但它和 volatile 有什么区别?

是的,synchronized 同样具备可见性语义:

区别在于粒度和开销:

最容易被忽略的一点:可见性问题往往在高并发下不暴露,而是在低负载、长时间运行或 JIT 优化后才突然复现——所以不能靠“测试没出错”来判断是否安全。