首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java中Volatile关键字详解

Java中Volatile关键字详解

原创
作者头像
用户3672714
发布2025-09-04 15:09:53
发布2025-09-04 15:09:53
11400
代码可运行
举报
运行总次数:0
代码可运行

好的,我来帮你整理一份 Java 中 volatile 关键字详解,从概念、原理、使用场景到注意事项,深入讲解并配示例代码。


🔹 1. volatile 简介

  • 类型:Java 关键字
  • 作用:确保 多线程环境下的可见性防止指令重排
  • 主要用于 轻量级同步,替代部分 synchronized 的场景

🔹 2. volatile 的核心特性

  1. 可见性(Visibility)
    • 一个线程修改了 volatile 变量,立即对其他线程可见
    • 普通变量在多线程下可能会被 CPU 缓存,其他线程不一定能立即看到
  2. 禁止指令重排序(Ordering)
    • 编译器和 CPU 在优化时可能会改变指令执行顺序
    • volatile 会在 读/写操作前后加入内存屏障(Memory Barrier),保证顺序
  3. 不保证原子性(Atomicity)
    • 自增 count++ 等操作不是原子操作
    • 对单次写入(赋值)是原子的,但复合操作需要额外同步

🔹 3. 使用场景

  1. 状态标志(Flag)
代码语言:javascript
代码运行次数:0
运行
复制
class Task implements Runnable {
    private volatile boolean running = true;

    public void stop() {
        running = false;
    }

    @Override
    public void run() {
        while (running) {
            // 执行任务
        }
        System.out.println("线程已停止");
    }
}
  • 一个线程修改 running,其他线程可以立即感知
  1. 单例模式(Double-Check Locking)
代码语言:javascript
代码运行次数:0
运行
复制
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 防止 对象未完全初始化就被其他线程访问

🔹 4. 内存模型(JMM)相关

  • volatileJava 内存模型(JMM) 密切相关
  • 保证:
    • 写操作先于后续读操作
    • 写入的值对所有线程立即可见
  • CPU 缓存和寄存器的优化不会影响 volatile 变量

🔹 5. 代码示例:可见性演示

代码语言:javascript
代码运行次数:0
运行
复制
class VolatileDemo {
    private static volatile boolean flag = true;

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            while (flag) {
                // 循环等待 flag 变为 false
            }
            System.out.println("线程结束");
        }).start();

        Thread.sleep(1000);
        flag = false; // 主线程修改 flag
        System.out.println("主线程修改 flag");
    }
}
  • 如果去掉 volatile,子线程可能 永远循环
  • 加上 volatile,子线程能及时感知变化

🔹 6. 注意事项

  1. 不能保证复合操作原子性
代码语言:javascript
代码运行次数:0
运行
复制
volatile int count = 0;
count++; // 不安全,可能丢失更新
  • 复合操作需用 synchronizedAtomicInteger
  1. 适用场景有限
    • 适合 状态标志、读多写少的场景
    • 不适合 计数器、累加器等高并发写操作
  2. 与 synchronized 对比 | 特性 | volatile | synchronized | |-----------------|-----------------|------------------| | 可见性 | ✔ | ✔ | | 原子性 | ✘ | ✔ | | 性能 | 高 | 相对低 | | 适用场景 | 状态标志、单例 | 复合操作、方法同步 |

✅ 总结

  • volatile轻量级同步工具,主要解决 可见性和顺序问题
  • 单次写入原子,但复合操作不保证原子性
  • 常用于 标志位、DCL单例模式 等场景
  • 高并发计数器等需要 AtomicXXXsynchronized

如果你愿意,我可以帮你画一张 volatile 内存可见性与指令重排示意图,让多线程概念更直观易懂。

你希望我画吗?

https://www.52runoob.com/archives/6675

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🔹 1. volatile 简介
  • 🔹 2. volatile 的核心特性
  • 🔹 3. 使用场景
  • 🔹 4. 内存模型(JMM)相关
  • 🔹 5. 代码示例:可见性演示
  • 🔹 6. 注意事项
    • ✅ 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档