volatile 关键字

Jul 18, 2019


volatile 两大特性

  1. 禁止重排序
  2. 内存可见性

volatile 修饰的变量和普通变量的区别

  1. 对于 volatile 变量:读操作时 JMM 会把工作内存中对应的值设为无效,要求线程从主内存中读取数据;写操作时 JMM 会把工作内存中对应的数据刷新到主内存中。这种情况下,其它线程就可以读取变量的最新值。
  2. 对于普通变量:读操作会优先读取工作内存的数据,如果工作内存中不存在,则从主内存中拷贝一份数据到工作内存中;写操作只会修改工作内存的副本数据。这种情况下,其它线程就无法读取变量的最新值。

所谓的内存可见性就是指:对于 volatile 修饰的变量,JVM 虚拟机保证从主内存加载到线程工作内存的值是最新的

详情见这里这里

ps:JMM(Java Memory Model):Java 内存模型

volatile 和 synchronized 的区别

出处见这里

  1. volatile 是告诉 JVM 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取
    synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞
  2. volatile 仅能使用在变量级别
    synchronized 可以直接使用在方法、代码块级别,间接用于变量和类级别
  3. volatile 仅能实现变量的可见性,不能保证原子性 synchronized 则可以保证变量的可见性和原子性
  4. volatile 不会造成线程阻塞 synchronized 可能会造成线程的阻塞
  5. volatile 标记的变量不会被编译器重排序 synchronized 标记的变量可以被编译器重排序

volatile 的应用场景

volatile 的应用场景需要满足两个条件:

  1. 对变量的写操作不依赖当前值
  2. 该变量没有包含在具有其它变量的不变式中

最常见的莫过于单例的双重检查加锁,详情见这里