java后端开发中volatile关键字有什么作用?

来源:IT编程作者:小何头衔:草根站长
导读:本期聚焦于小伙伴创作的《java后端开发中volatile关键字有什么作用?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《java后端开发中volatile关键字有什么作用?》有用,将其分享出去将是对创作者最好的鼓励。

在java后端开发的多线程编程场景中,volatile是保证变量线程安全的重要关键字之一,它的作用主要围绕多线程下的内存交互和指令执行顺序展开,能够解决部分并发场景下的数据不一致问题。

java后端开发中volatile关键字有什么作用?

volatile的核心作用

1. 保证内存可见性

在java内存模型中,每个线程有自己的工作内存,线程操作变量时会从主内存拷贝副本到工作内存,操作完成后再写回主内存。普通变量修改后,其他线程无法立即感知到变化,而volatile修饰的变量会有特殊规则:线程修改volatile变量后会立即刷新到主内存,同时其他线程工作内存中该变量的副本会失效,必须重新从主内存读取,以此保证所有线程看到的变量值是一致的。

以下是一个简单的可见性示例:

// 未加volatile的变量,线程可能无法感知到修改
private static boolean flag = false;

// 加volatile的变量,修改后其他线程可立即感知
private static volatile boolean volatileFlag = false;

public static void main(String[] args) throws InterruptedException {
    // 测试普通变量
    Thread t1 = new Thread(() -> {
        while (!flag) {
            // 空循环,等待flag被修改
        }
        System.out.println("普通变量flag被修改,线程结束");
    });
    t1.start();
    Thread.sleep(1000);
    flag = true;
    // 这里t1可能不会结束,因为看不到flag的修改

    // 测试volatile变量
    Thread t2 = new Thread(() -> {
        while (!volatileFlag) {
            // 空循环,等待volatileFlag被修改
        }
        System.out.println("volatile变量volatileFlag被修改,线程结束");
    });
    t2.start();
    Thread.sleep(1000);
    volatileFlag = true;
    // 这里t2一定会结束,因为volatile保证了可见性
}

2. 禁止指令重排

为了优化执行效率,编译器和处理器可能会对指令进行重排序,只要重排序后单线程下的执行结果不变,重排序就是允许的。但在多线程场景下,指令重排可能导致逻辑错误。volatile会通过内存屏障禁止特定类型的指令重排:

  • 在volatile写操作前插入StoreStore屏障,禁止上面的普通写和volatile写重排
  • 在volatile写操作后插入StoreLoad屏障,禁止volatile写和后面的读操作重排
  • 在volatile读操作后插入LoadLoad屏障,禁止volatile读和后面的普通读重排
  • 在volatile读操作后插入LoadStore屏障,禁止volatile读和后面的普通写重排

典型的双重检查锁单例模式中就需要用volatile禁止指令重排:

public class Singleton {
    // 必须用volatile修饰,禁止指令重排
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    // 如果不加volatile,这里可能发生指令重排:
                    // 1. 分配内存 2. 指向内存地址 3. 初始化对象
                    // 若2和3重排,其他线程可能拿到未初始化的对象
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

volatile的适用场景

volatile并不是万能的,它只适合以下两类场景:

  • 变量的写操作不依赖当前值,或者只有单个线程修改变量值,比如状态标记位,像上面的flag示例,只有主线程修改flag,其他线程只读
  • 变量不参与不变式约束,也就是变量不需要和其他变量共同配合来完成某个逻辑判断

volatile和synchronized的区别

很多开发者会混淆两者的作用,它们的核心区别如下:

对比维度volatilesynchronized
原子性不保证复合操作原子性,比如volatile++不是原子操作保证代码块的原子性,同一时间只有一个线程执行
可见性保证保证,因为解锁前会刷新变量到主内存
有序性禁止指令重排保证,因为同一时间只有一个线程执行,相当于单线程环境
性能更轻量,不会阻塞线程重量级,会阻塞线程,性能开销更大

如果需要对变量的复合操作保证原子性,比如计数器的自增操作,就不能只用volatile,需要配合synchronized或者使用AtomicInteger等原子类来实现。

volatilejava多线程内存可见性指令重排修改时间:2026-06-20 05:30:29

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。