重排序
为了提高编译器和处理器的能力,对代码编译执行顺序进行修改
// a和b没有依赖关系,编译时可能会是b先执行在执行a
int a = 1
int b = 2
// 下面由于b依赖于a,所以不会进行重排序
int a = 1
int b = a + 1
volatile
当一个线程对共享变量进行修改,其他线程可以立即知道新的共享变量的值,防止重排序
- 每次使用时立即从主内存刷新
- read,load,use必须连续出现
- assign,store,write必须连续出现
双检锁单例模式
mInstance没有被volatile修饰是不正确的
当线程A调用getInstance方法时,走到第4步,有可能会发生重排序
第4步的执行可分为
1. 分配一块内存
2. 初始化
3. mInstance指向这块内存
发生重排序上面顺序有可能1,3,2
如果此时线程B也来调用getInstance方法,在mInstance== null时正好线程A走到了“mInstance指向这块内存”,此时mInstance不为null,但还没有初始化。线程B拿到的就是有问题的引用
public class Singleton {
// 正确写法private static volatile Singleton mInstance;
private static Singleton mInstance;
private Singleton(){
}
public static Singleton getInstance(){
if(mInstance== null){ // 第1步
synchronized(Singleton.class){ // 第2步
if(mInstance== null){ // 第3步
mInstance= new Singleton(); // 第4步
}
}
}
return mInstance; // 第5步
}
}