1、volatile关键字的作用
用于保持内存可见性(随时见到的都是最新值)和防止指令重排序。
2、volatile如何保持内存可见性
内存可见性:所有线程都能看到共享内存的最新状态。
Java通过几种原子操作完成工作内存和主内存的交互:
lock:作用于主内存,把变量标识为线程独占状态。
unlock:作用于主内存,解除独占状态。
read:作用主内存,把一个变量的值从主内存传输到线程的工作内存。
load:作用于工作内存,把read操作传过来的变量值放入工作内存的变量副本中。
use:作用工作内存,把工作内存当中的一个变量值传给执行引擎。
assign:作用工作内存,把一个从执行引擎接收到的值赋值给工作内存的变量。
store:作用于工作内存的变量,把工作内存的一个变量的值传送到主内存中。
write:作用于主内存的变量,把store操作传来的变量的值放入主内存的变量中。
volatile的特殊规则就是:
read、load、use或者assign、store、write动作必须连续出现。
使用volatile变量能够保证:每次读取前必须先从主内存刷新最新的值。每次写入后必须立即同步回主内存当中。
3、volatile如何防止指令重排
防止指令重排:在基于偏序关系的Happens-Before内存模型中,指令重排技术大大提高了程序执行效率。
volatile关键字通过"内存屏障"来防止指令被重排序。
为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
//懒加载示例
class Singleton {
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance() {
//当instance不为null时,仍可能指向一个"被部分初始化的对象"
//需要用volatile来修饰instance避免发生指令重排序
if ( instance == null ) {
synchronized (Singleton.class) {
if ( instance == null ) {
instance = new Singleton();
}
}
}
return instance;
}
}
网友评论