java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java volatile关键字

java中volatile关键字解释说明

作者:菜鸡上道

volatile是Java中的一个关键字,用于修饰变量,保证其可见性和禁止指令重排序,但不保证原子性,下面我们从原理层面详细解析volatile 的工作机制,感兴趣的朋友跟随小编一起看看吧

在 Java 中,volatile 是一个轻量级的同步机制关键字,用于修饰字段(变量),其核心作用是:

保证变量的“可见性”和“禁止指令重排序”,但不保证原子性。

下面我们从原理层面详细解析 volatile 的工作机制。

一、三大特性:可见性、有序性、原子性

特性volatile 是否支持说明
可见性(Visibility)✅ 支持一个线程修改了 volatile 变量,其他线程能立即看到最新值
有序性(Ordering)✅ 支持(禁止重排序)JVM 和 CPU 不会对 volatile 读写进行重排序优化
原子性(Atomicity)❌ 不支持(除 long/double 的简单读写)i++ 这类复合操作不是原子的

二、volatile 的底层原理(基于内存模型)

1.Java 内存模型(JMM)背景

问题:如果没有同步机制,线程 A 修改了变量,线程 B 可能永远看不到新值(因为读的是本地缓存)。

2.volatile 如何解决可见性?

当一个字段被声明为 volatile

这相当于每次读写都强制与主内存同步。

3.内存屏障(Memory Barrier / Memory Fence)

JVM 在编译 volatile 读写时,会插入内存屏障指令,实现两个效果:

(1)禁止指令重排序

例如:

// 假设 flag 是 volatile
a = 1;          // 普通写
flag = true;    // volatile 写

a = 1 一定发生在 flag = true 之前,不会被重排序。

(2)强制刷新缓存

这些屏障由 JVM 根据不同 CPU 架构(x86、ARM 等)生成对应的底层指令(如 lock 前缀指令)。

三、典型应用场景

✅ 场景 1:状态标志位(最常见)

public class TaskRunner {
    private volatile boolean running = true;
    public void stop() {
        running = false; // 其他线程能立即看到
    }
    public void run() {
        while (running) {
            // do work
        }
    }
}

若不用 volatilerun() 方法可能因读取本地缓存而永远无法退出。

✅ 场景 2:单例模式中的双重检查锁定(DCL)

public class Singleton {
    private static volatile Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // 防止重排序导致未初始化完成就被引用
                }
            }
        }
        return instance;
    }
}

如果没有 volatilenew Singleton() 的三步(分配内存、初始化、赋值)可能被重排序为“分配 → 赋值 → 初始化”,导致其他线程拿到未初始化的对象。

❌ 不适用场景:复合操作(非原子)

private volatile int count = 0;
public void increment() {
    count++; // 实际是:读取 count → +1 → 写回,非原子!
}

此时应使用 AtomicInteger 或加锁。

四、与 synchronized 的区别

特性volatilesynchronized
保证可见性
保证原子性❌(除简单读写)
保证有序性✅(禁止重排序)✅(隐式包含)
性能开销低(无锁)较高(涉及 Monitor 锁)
适用范围仅变量方法/代码块/变量

volatilesynchronized 的轻量替代方案,但功能更弱。

五、补充:long 和 double 的特殊性

Java 规范规定:

总结

volatile 的核心原理是:

  1. 通过内存屏障实现变量的可见性
  2. 禁止编译器和处理器重排序,保证有序性
  3. 不提供原子性,不能用于复合操作。

适用条件

当一个变量被多个线程访问,且满足:

  • 写操作不依赖当前值(如 flag = true
  • 或者只有一个线程写,其他线程只读

否则,请使用 synchronizedReentrantLockjava.util.concurrent.atomic 包中的原子类。

如需进一步了解内存屏障或 JMM 模型,也可以继续提问!

到此这篇关于java中volatile关键字解释说明的文章就介绍到这了,更多相关java volatile关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文