在学习关于cpu基础的知识的过程中,看到了有关volatile的一个小知识点,本篇属于随笔,记录一下东西。简单开展,简单阐述。
提出问题:DCL中实例一定需要volatile修饰吗?
先来看看DCL的代码
private volatile static SafeLanHanSingleton instance;
private SafeLanHanSingleton(){}
public static SafeLanHanSingleton getInstance(){
if(instance == null){ // Step 1
synchronized(SafeLanHanSingleton.class){//Step 2
if(instance == null){ // Step 3
instance = new SafeLanHanSingleton(); //Step 4
}
}
}
return instance;
}
我们都知道双层判断是否为空可以解决产生多个实例的问题。完成了单例模式,那volatile的作用的是什么呢?
先来看看new 一个对象会发生什么事情
主要看0 4 7 这三行,可以看到在new 一个对象的时候,有三步重要的步骤
0 这行 代表new了一个新的实例出来,但是可以看到在4 这行的时候,它才调用了类的init方法,也就是构造函数。比如T 这个类里面如果有个变量 int m = 40;的话,那么0这行的时候,它其实只是把M给分配了个地址,并实现int的初始化而已,把0赋值给这个m。
根据cpu的指令重排序的话,如果没有volatile的修饰,那么其实是有可能出现 0 7 4 的步骤,也就是说先把m = 0;然后存储了起来,但是如果是对于高并发的多线程的而言,那么就有可能出现这种情况, 线程一 ->把m = 0;然后存储了起来,并且这个是个单例模式,然后其他线程拿到这个单例的时候,m就会是0,而不是40;这样就造成严重错误,如果这m是跟钱相关,那么可想而知,公司就有可能因为这个细小的问题造成了损失。