volatile与内存可见性

本文最后更新于 2024年10月19日

Java 内存模型 (JMM) 中的一个核心问题是线程对共享变量的可见性。在多线程环境中,每个线程都有自己的工作内存(即 CPU 缓存)。当一个线程修改了某个变量,其他线程并不能立即看到这个修改,因为每个线程可能都在使用自己工作内存中的缓存值。

volatile 的可见性机制:

  • 强制刷新主内存:当一个线程对 volatile 修饰的变量进行写操作时,修改后的值会立即被刷新到主内存中,而不是缓存在该线程的工作内存中。

  • 强制读取主内存:当一个线程对 volatile 修饰的变量进行读操作时,会直接从主内存中读取最新值,而不会从线程的工作内存中读取缓存的值。

  • 示例代码

public class TestVolatile {
    
    static volatile boolean flag = false;
    
    public static void main(String[] args) {
        
        new Thread(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            flag = true;
            
            System.out.println("子线程修改flag的值为:  " + flag);
            
        }).start();
        
        
        // while(true) 调用底层代码,效率极高,不会从主存中再次获取被其他线程修改过的数据
        while (true) {
            if (flag) {
                System.out.println("flag is true 主线程结束循环!");
                break;
            }

        }

    }
}

因此,volatile 保证了变量的可见性,即当一个线程修改了 volatile 变量后,其他线程能够立即看到最新的值。

volatile 与 synchronized 的对比

特性 volatile synchronized
可见性 保证可见性 保证可见性
原子性 不保证原子性 保证原子性
重排序 禁止指令重排序 保证顺序执行
性能开销 较低(无锁机制) 较高(加锁/解锁开销)
使用场景 适用于简单状态标志位或单次读写 适用于复杂的临界区保护

volatile与内存可见性
https://blog.liuzijian.com/post/2dca932a-b1b5-48ca-b60f-2f93e7232c4a.html
作者
Liu Zijian
发布于
2022年5月1日
更新于
2024年10月19日
许可协议