volatile关键字的理解
一、volatile是什么
volatile是JVM虚拟机提供的轻量级的同步机制:
- 保证可见性:当数据存储到主内存中时,其他线程要使用数据,会将其拷贝一份到自己的工作内存中进行操作,改变数据后再赋值给主内存,为了保证与其他线程数据同步,需要通知其他已拿到拷贝数据的线程。volatile修饰的数据,会将线程名称作为key进行存储。
- 不保证原子性:多线程环境中可能出现数据写入丢失的情况。可以使用Atomic原子包装类保证数据的原子性。
- 禁止指令重排:指令重排是编译器或处理器在执行文件时进行指令重排优化,多线程情况下可能出现乱序执行,导致数据失去准确性。
二、JMM内存规则
- 保证可见性:使用关键字volatile
- 原子性:动作执行的完整性。
- 有序性
三、DCL单例模式使用volatile
- 单例源码:
public class SingletonDemo {
private static volatile SingletonDemo instances = null;
private SingletonDemo() {}
publuc static SingletonDemo getInstances() {
if (instances == null) {
synchronized(SingletonDemo.class) {
if (instances == null) {
instances = new SingletonDemo();
}
}
}
return instances;
}
}
- 使用volatile解析:多线程情况下,编译器或处理器可能出现指令重排优化。new对象的执行步骤如下
- 分配内存空间
- 进行对象初始化操作,也就是执行init()
- 赋值内存地址,此时instances != null
如果在进行new对象的时候发生指令重排,变成了先赋值内存地址,再执行初始化,那么就可能有线程获取到只有内存地址没有初始化实例的对象,发生异常。而volatile能够禁止编译器或处理器进行指令重排,符合JMM原则,保证了操作执行的有序性。