private static volatile User user; //第一步
public User getIns(){
if(Objects.isNull(user)){ //第二步
synchronized (User.class){ //第三步
if(Objects.isNull(user)){ //第四步
user = new User(); //第五步
}
}
}
return user;
}
问题是:针对第五步代码 user = new User()
有三步操作
- 分配内存
- 初始化对象
- 设置instance指向刚分配的地址
这三步在编译器运行时,可能会出现指令重排序, 从1-2-3 排序为1-3-2
多线程场景举例:
例如现在有两个线程A,B。线程A在执行第5步代码时,B线程进到第二步代码,而此时A执行了 1(分配内存 )和3(设置instance指向刚分配的地址),还没有执行2初始化对象, 但是3方法已经指向了一个对象,也就是说此时对象不为null,只是没初始化。那么此时B线程判断user不为null, 就直接返回一个未初始化的对象,就会出现问题了。
而用了volatile,上面的重排序就会在多线程环境中禁止,只会按照1-2-3执行,就不会出现上述问题。