Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
      • 1. volatile 解决什么
      • 2. 可见性
      • 3. 禁止重排序
      • 4. volatile 不能保证原子性
      • 5. volatile happens-before
      • 6. 适用场景
      • 7. 双重检查锁
      • 8. volatile 与 synchronized
      • 专家实践与边界
      • Tips 快问快答
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

volatile关键字

volatile 是 Java 中最轻量的可见性工具。它能保证变量修改对其他线程可见,并禁止特定指令重排序,但不能保证复合操作的原子性。

# 1. volatile 解决什么

private volatile boolean running = true;

public void stop() {
    running = false;
}

public void run() {
    while (running) {
        doWork();
    }
}

如果没有 volatile,工作线程可能长期看不到 running=false。

# 2. 可见性

普通变量:

线程 A 修改 shared = 1
  │
  ▼
修改可能暂存在工作内存/缓存

线程 B 读取 shared
  │
  ▼
可能仍看到旧值

volatile 变量:

线程 A 写 volatile
  │
  ▼
对其他线程可见

线程 B 读 volatile
  │
  ▼
看到最新写入结果

# 3. 禁止重排序

volatile 写和读会建立内存屏障,限制指令重排序。

典型场景:状态标记。

data = loadData();
ready = true; // volatile

另一个线程:

if (ready) {
    use(data);
}

ready 是 volatile 时,写 ready=true 之前对 data 的写入,对读到 ready=true 的线程可见。

# 4. volatile 不能保证原子性

private volatile int count;

public void increment() {
    count++;
}

count++ 包含三步:

读 count
加 1
写 count

volatile 只能保证每次读写可见,不保证三步合成一个不可分割操作。

多线程计数应使用:

AtomicInteger count = new AtomicInteger();
count.incrementAndGet();

或加锁。

# 5. volatile happens-before

规则:

对 volatile 变量的写
happens-before
后续对同一个 volatile 变量的读

示意:

// 线程 A
config = newConfig;
initialized = true; // volatile 写

// 线程 B
if (initialized) {  // volatile 读
    use(config);
}

线程 B 读到 initialized=true 后,也能看到线程 A 在此之前写入的 config。

# 6. 适用场景

适合:

  • 状态标记。
  • 开关控制。
  • 单写多读配置引用。
  • 双重检查锁中的实例引用。
  • 发布不可变对象引用。

不适合:

  • 复合操作,例如 i++。
  • 多字段一致性。
  • 需要互斥的临界区。
  • 条件等待和通知。

# 7. 双重检查锁

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;
    }
}

volatile 防止对象引用赋值与构造初始化之间发生对外可见的重排序。

对象创建概念步骤:

分配内存
初始化对象
引用指向内存

如果引用先对外可见,其他线程可能拿到未初始化完成的对象。

# 8. volatile 与 synchronized

对比项 volatile synchronized
可见性 保证 保证
有序性 保证特定顺序 保证临界区顺序
原子性 单次读写 临界区整体
阻塞 不阻塞 可能阻塞
适用 状态标记、发布引用 复合操作、多字段一致性

volatile 是轻量工具,不是锁的替代品。

# 专家实践与边界

volatile 的关键是“轻量可见性”,不是“轻量锁”。它适合状态标记、配置引用发布、单写多读开关,不适合保护多个变量之间的不变量。

线程 A 写 volatile
  │ 刷新写入并建立 happens-before
  ▼
线程 B 读 volatile
  │ 看到最新值
  ▼
后续读操作也能看到写入前的相关状态
场景 是否适合 volatile 原因
停止标记 适合 单变量可见性
配置对象整体替换 适合 引用不可变或安全发布
count++ 不适合 不是原子操作
多字段一致性 不适合 需要锁保护不变量
双重检查单例 可用 需要禁止重排序

排查 volatile 相关 bug 时,要看代码是否把“看到最新值”误解成“复合操作安全”。如果一个判断后面跟着修改共享状态,通常已经超出 volatile 的能力范围。

# Tips 快问快答

Q:volatile 保证什么? A:保证可见性,并禁止相关指令重排序。

Q:volatile 能保证 i++ 原子吗? A:不能,i++ 是复合操作。

Q:volatile 会加锁吗? A:不会,它不会让线程阻塞。

Q:什么时候适合 volatile? A:状态开关、单写多读标记、发布不可变对象引用。

Q:volatile 和 synchronized 最大区别是什么? A:volatile 不提供互斥,synchronized 提供互斥和临界区原子性。

Q:双重检查锁为什么要 volatile? A:防止实例引用在对象初始化完成前对其他线程可见。

Q:volatile 读到 true 后能看到之前写入的数据吗? A:能,volatile 写 happens-before 后续同变量 volatile 读。

Q:多个变量一致性可以靠 volatile 吗? A:通常不能,需要锁或不可变对象整体发布。

上次更新: 2026/06/25, 14:19:18
synchronized关键字
Java内存模型(JMM)

← synchronized关键字 Java内存模型(JMM)→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式