volatile关键字

用法

volatile通常被比喻成”轻量级的synchronized“,也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是一个变量修饰符只能用来修饰变量,无法修饰方法及代码块等

原理

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的
  • 禁止进行指令重排序

对于volatile修饰的变量,当对变量进行写操作的时候,JVM会向处理器发送一条lock前缀的指令,将这个缓存中的变量回写到系统主存中
所以一个变量被volatile所修饰的话,在每次数据变化之后,其值都会被强制刷入主存。而其他处理器的缓存由于遵守了缓存一致性协议,也会把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中,其值在多个缓存中是可见的

volatile在Java中的并发保障

volatile与可见性

Java中的volatile关键字提供了一个功能,那就是被其修饰的变量在被修改后可以立即同步到主内存,被其修饰的变量在每次是用之前都从主内存刷新。因此,可以使用volatile来保证多线程操作时变量的可见性

volatile与有序性

volatile可以禁止指令重排,这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。被volatile修饰的变量的操作,会严格按照load->add->save 的顺序执行

volatile与原子性

volatile无法保证原子性,在以下两个场景中可以使用volatile来代替synchronized:

  • 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程会修改变量的值。
  • 变量不需要与其他状态变量共同参与不变约束

除以上场景外,都需要使用其他方式来保证原子性,如synchronized或者concurrent包

参考链接