volatile

不可见性问题示例1

public class Test {
    
    // 加 volatile 就能解决
    public static Integer flag = 1;

    public static void main(String[] args) {
        // 线程 A 死循环,当 a == 1 时不会停止,当 a != 1 时按理来说就会停止
        new Thread(() -> {
            while (flag == 1){
                
            }
        }, "线程A").start();

		// 线程 B 两秒后修改 a 的值
        new Thread(() -> {
            LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
            flag = 2;
        }, "线程B").start();
    }
}

2 秒后,线程 B 修改变量 a 的值,如果线程 A 能及时知道 a 的值已变化就会停止,实际情况是不会停止的

不可见性问题示例2

经典的双重检查案例

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {
        // 私有构造函数防止外部实例化
    }

    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

如果不加 volatile,有可能导致问题,具体分析下导致什么问题,什么原因导致的,以及为什么加了 volatile 就能解决问题

首先要明白 new 的过程分为三个步骤:分配内存、初始化属性、地址引用

线程A 线程B
第一次检查是 null 第一次检查也是 null 第一次没做同步,两个线程可能同时进入
拿到锁,进入同步块 拿不到锁,等待
第二次检查,还是 null
开始创建对象
释放锁 拿到锁,进入同步块
回写主存 第二次检查,还是 null 因为线程 A 还没回写完主存,其实对象已经创建了,但是线程 B 不可见
要是有 volatile 修饰,线程 A 的修改对于线程 B 就是立即可见的,就可以避免问题
开始创建对象
释放锁
回写主存

volatile 原理

可见性

可以理解为,每个线程不是读取自己的工作内存,而是直接读取主内存,每次修改都会立即回写主内存(也可以理解为当更新后别的线程的副本变量会失效,会强制别的线程重新读取最新的值),更深入的原因是缓存一致性,官方描述如下(不是很理解,后面再看):

当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取

有序性

java 代码最终翻译成可执行的机器指令会被优化、或者只能保证赋值操作啥的是准确的,但是不一定就是我们写的代码的顺序,这就是 指令重排序,底层使用内存屏障来完成的,对于 volatile 完整的情况应该是这样的(不是很理解,后面再看)

  1. 在每一个volatile的写(store)之前,加入一个StoreStore屏障和一个LoadStore屏障
  2. 在每一个volatile的写(store)之后,加入一个StoreLoad屏障和一个StroeStore屏障
  3. 在每一个volatile的读(load)之后,加一个LoadLoad屏障和LoadStrore屏障
posted @   CyrusHuang  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示