volatile 是java提供的一个轻量级的同步机制。
并发编程:需满足原子性,可见性,有序性
原子性:一个操作或多个操作要么都执行,要么都不执行
可见性:当多个线程访问同一个变量时,一个线程修改了变量的值,则其他线程能够立即见到修改后的值。
有序性:程序执行的顺序按照代码的先后顺序。
锁的特性:互斥性和可见性
volatile 修饰的变量
1、保证可见性,
(1)当写一个volatile变量时,JMM会把该线程本地内存中的变量强制刷新到主内存中
(2)该写操作,会导致其他线程中的volatile变量缓存无效。
2、禁止指令重排
执行到volatile变量时,其前面的语句都执行完,后面的语句都未执行,且前面语句执行结果对volatile变量及其后面的语句可见。
重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。重排序需要遵守一定规则:
(1)重排序操作不会对存在数据依赖关系的操作进行重排序。
(2)重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果不能被改变。
volatile原理:
如果把加入volatile关键字的代码和未加入volatile关键字的代码都生成汇编代码,会发现加入volatile关键字的代码会多出一个lock前缀指令。 lock前缀指令实际相当于一个内存屏障,
内存屏障提供了3种功能:
1.重排序时不能把后面的指令重排序到内存屏障之前的位置
2. 它会强制将对缓存的修改操作立即写入主存;
3.写操作会引起别的CPU或者别的内核缓存失效,相当于让新写入的值对别的线程可见。
使用:
单例模式的双重锁
public class Singleton{
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null)
instance = new Singleton();
}
}
return instance;
}}
这是一种懒汉的单例模式,使用时才创建对象,而且为了避免初始化操作的指令重排序,给instance加上了volatile