Fork me on GitHub

懒加载和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地址

https://gitee.com/zhuayng/foundation-study/blob/develop/JavaBasis/JVM/src/main/java/com/yxkj/jvm/basic/LazySingleton.java

posted @ 2022-02-18 19:37  晨度  阅读(46)  评论(0编辑  收藏  举报