懒加载和volatile
简介
懒加载指在多线程环境中,只创建一个实例对象。
代码
public class LazySingleton {
private static volatile LazySingleton instance= null;
public static LazySingleton getSingleton(){
if (instance==null){ //提高效率,不需要每次加锁完成再去判断是不是空
synchronized (LazySingleton.class){
if (instance==null){ //防止创建多个实例
instance=new LazySingleton();
}
}
}
return instance;
}
}
懒加载为啥要加上volatile
- 对象创建过程
- 申请内存
- 初始化
- 返回地址
其中初始化与返回地址没有必然的依赖关系符合指令重排序的条件,那么cpu在执行jvm创建过程中如果不加volatile就会出现返回地址但是对象的初始化没有完成(对象不可用),这就是半初始化问题,半初始化意味着对象的创建没有完成,当我们使用此对象的时候就会报错。
为什么不能所有的java代码都用volatile来防止重排序?
- CPU的速度至少比内存快100倍,为了提升效率,会打乱原来的执行效率,会在一条指令执行过程中(比如去内存读数据,大概慢100多倍),去同时执行另一条指令,前提是两条指令没有依赖关系。 提升效率只占这个问题的很小一部分。
- cpu执行过程中的缓存问题:缓存中的数据是以行为单位进行存储,我们称之为缓存行。而cpu与高速缓存的数据交换是以字为单位进行交换,列如64位计算机一次能够执行两个双字,在多线程情况下,如果需要修改“共享同一个缓存行的变量”,就会无意中影响彼此的性能,这就是伪共享。伪共享问题十分耗费cpu性能。
Gitee地址
XFS