volatile关键字的作用【全网最全且易懂】

一、前言

  • volatile是Java中作用于多线程并发环境下的核心关键字。
  • 其作用是确保共享变量的可见性和有序性,但不保证原子性

二、保证可见性(Visibility)

  • 当变量被volatile修饰时,所有线程对该变量的修改会强制立即刷回主内存
  • 其他线程每次读取时也会强制从主内存重新加载,确保所有线程看到的变量值是最新的。
  • 代码示例(无volatile导致死循环)
public class VisibilityDemo {
    // 去掉 volatile 后,子线程可能无法感知主线程的修改
    private volatile boolean flag = true;

    public void runTask() {
        new Thread(() -> {
            System.out.println("子线程启动");
            while (flag) { /* 空循环 */ }
            System.out.println("子线程停止");
        }).start();
    }

    public static void main(String[] args) throws InterruptedException {
        VisibilityDemo demo = new VisibilityDemo();
        demo.runTask();
        Thread.sleep(1000);
        demo.flag = false; // 主线程修改标志位
        System.out.println("主线程修改完成");
    }
}
  • 结果说明
    • 无volatile时:子线程可能因缓存未更新而陷入死循环。
    • 有volatile时:子线程能立即感知到flag变化,正常退出。

三、禁止指令重排序(Ordering)

  • volatile通过内存屏障(Memory Barrier) 禁止编译器和处理器对代码执行顺序的优化;
  • 确保多线程环境下关键操作的执行顺序符合预期。
  • 代码示例(单例模式双重检查锁)
public class Singleton {
    private static volatile Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    // 非原子操作:分配内存 → 初始化对象 → 赋值引用
                    // 若无volatile,可能因指令重排返回未初始化的对象
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 关键点:
    • 单例模式中,使用volatile来禁止指令重排序,从而避免未完全初始化的对象被使用。
    • 若instance不加volatile,其他线程可能拿到未完成初始化的对象(半初始化状态)。
    • volatile确保new Singleton()的指令顺序不被重排

四、volatile的局限性

  • 无法保证原子性(Atomicity)
public class AtomicityDemo {
    private volatile int count = 0;

    public void increment() {
        count++; // 实际是3步操作:读取 → 修改 → 写入
    }
}
  • 问题:多线程并发执行count++时,最终结果可能小于预期。
  • 解决方案:改用AtomicIntegersynchronized

五、适用场景

  • 状态标志位:如开关控制(flag变量)。
  • 单次安全发布:确保对象初始化完成后再被引用(如单例模式)。
  • 独立观察:变量不依赖其他状态(如定期更新的温度值)。

六、拓展

1.底层原理

  • 可见性:通过CPU的缓存一致性协议(如MESI)强制同步主内存数据
  • 禁止重排序:在读写操作前后插入LoadStore/StoreStore等内存屏障指令。

2.和synchronized的区别

  • 性能:
    • volatile 是一种轻量级的同步机制,开销较小,但它只能用于变量的可见性和禁止重排序,无法实现复杂的同步逻辑。
    • synchronized则是重量级的同步机制,可以保证代码块的原子性和可见性,但开销较大。
  • 使用场景:
    • volatile 适用于简单的状态标志、标记等场景。
    • 而 synchronized 更适合复杂的临界区保护,需要确保多个操作的原子性时。

七、总结

  • volatile是轻量级同步机制,适用于需要保证可见性有序性场景,但需结合原子类或锁处理复合操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值