volatile

volatile是什么

volatile是Java虚拟机提供的轻量级的同步机制,是 Java 的一个关键字。volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。 当某个变量是共享变量,且这个变量是被 volatile 修饰的,那么在修改了这个变量的值之后,再读取该变量的值时,可以保证获取到的是修改后的最新的值,而不是过期的值。

  • 保证可见性
  • 不保证原子性
  • 禁止指令重排

内存可见性(Memory Visibility)

标记为 volatile 的变量,对一个线程的写操作,会立即被刷新到主内存;对另一个线程的读操作,则总是从主内存中获取最新的值。这样一来,一个线程对 volatile 变量的修改,能够被其他线程及时"看见"。

java 复制代码
class Worker extends Thread {
  private volatile boolean running = true;

  public void run() {
    while (running) {
      // 工作逻辑
    }
  }

  public void shutdown() {
    running = false;
  }
}

禁止指令重排序(Prevents Reordering)

在 JMM 中,普通操作可因编译器或处理器优化而乱序执行,但对 volatile 变量的读写具有"内存屏障"效果:

  • 写入 volatile 变量之前的所有操作,在内存屏障之前,必须先执行完成。
  • 读取 volatile 变量之后的所有操作,在内存屏障之后,才能开始执行。

这保证了对 volatile 变量前后的操作不会被重排序,从而提供了一定的执行顺序。

java 复制代码
class Singleton {
    private static volatile Singleton instance; // 必须 volatile!
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // 禁止重排序,避免返回未初始化对象
                }
            }
        }
        return instance;
    }
}

底层原理

屏障类型 作用
LoadLoad 禁止 volatile 读与后续普通读重排序
LoadStore 禁止 volatile 读与后续普通写重排序
StoreStore 禁止 volatile 写之前的普通写与 volatile 写重排序(确保写操作可见)
StoreLoad 禁止 volatile 写与后续 volatile 读/写重排序(全能屏障,开销最大)

在每个volatile读操作的后面插入一个LoadLoad屏障;

在每个volatile读操作的后面插入一个LoadStore屏障。

在每个volatile写操作的前面插入一个StoreStore屏障;

在每个volatile写操作的后面插入一个StoreLoad屏障;

需要注意的是:volatile写是在前面和后面分别插入内存屏障,而volatile读操作是在后面插入两个内存屏障

局限性

不保证复合操作的原子性 对 volatile 变量进行 ++、--、+= 等不是原子操作,仍需额外同步或使用原子类(AtomicInteger 等)。

不能替代锁 对于涉及多个变量之间的一致性维护,volatile 无法保证"原子性和可见性的一致性",必须使用锁(synchronized、ReentrantLock)或原子类。

性能开销 虽然比锁轻量,但频繁对 volatile 变量的读写仍会引入内存屏障,影响 CPU 的乱序优化和缓存一致性性能。只在确有需求时使用。

不支持"等待-通知"机制 与 synchronized 不同,volatile 无法实现 wait()、notify() 等线程协调方法。

相关推荐
ZealSinger5 分钟前
LangChain4j用AiServices拼Tool
java·rag·ai智能体·langchain4j
vx_Biye_Design13 分钟前
springboot高校选课系统82776-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
Sweet锦1 小时前
不调 Python,不装向量库:我用纯 Java 写了一套以图搜图引擎
java·人工智能·开源·图搜索
打工仔折腾 AI2 小时前
LLaMA 1 到 LLaMA 3 架构演进拆解:从 RoPE、GQA 到词表扩张
人工智能·后端·python·深度学习·langchain·llama
如意猴2 小时前
【C++】007 C/C++ 内存管理机制、malloc与new的区别及模板初阶
java·c++·算法
可乐鸡翅yeah_2 小时前
HLS 分片过期清理,直播旧 TS 分片磁盘爆满问题处理
java·后端·spring·m3u8·m3u8在线·音视频在线播放
张彦峰ZYF2 小时前
加了锁不等于扛得住争用:synchronized、显式锁与 CAS 的语义分层、争用代价账本与选型判据
后端·同步设施·内置锁的四种状态与单向升级·可重入的由来与四条硬边界·显式锁的状态字段与等待队列·读写锁与邮戳锁·一次同步的开销账本
专业程序开发源3 小时前
SSM校园拍摄交流服务平台36936-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·php·课程设计
Gopher_HBo3 小时前
zap采样器与性能优化内幕
后端