当前位置 > it书童 > java > 正文

Double check 双重检查实现单例模式

java it书童 2020-12-26 18:29:51 0赞 0踩 99阅读 0评论

代码如下:

public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton;

    private LazyDoubleCheckSingleton() {
    }

    public static LazyDoubleCheckSingleton getInstance() {
        if (lazyDoubleCheckSingleton == null) { // 这层判断,可以大幅度减少 synchronized 在方法上造成的开销
            // 锁定了该类
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazyDoubleCheckSingleton == null) {
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                    // 实例化代码的三个步骤 实际过程,2 和 3 可能会倒置
                    // 1.分配内存给这个对象
                    // 2.初始化对象
                    // 3.设置 LazyDoubleCheckSingleton 指向刚分配的内存地址
                }
            }
        }
        return lazyDoubleCheckSingleton;
    }
}

Double check 是为了兼顾性能与安全,不必每次都直接加锁,加锁是有成本的。

用两个判断的原因:

同步锁外判断,为避免在实例已经创建的情况下每次获取实例都加锁取,影响性能;

锁内判断,考虑多线程情况下,两个以上线程都已经运行至同步锁处,也就是都已经判断变量为空,如锁内不再次判断,会导致实例重复创建

此外还要防止实例化内存的重排序导致的隐患

实例化代码的三个步骤 实际过程,2 和 3 可能会倒置

1.分配内存给这个对象

2.初始化对象

3.设置 LazyDoubleCheckSingleton 指向刚分配的内存地址

2 和 3 的重排序并不会影响最终结果

如果是多线程可能就有以下隐患

解决:使用 volatile 关键字,不允许2和3重排序

关于我
一个文科出身的程序员,追求做个有趣的人,传播有价值的知识,微信公众号主要分享读书思考心得,不会有代码类文章,非程序员的同学请放心订阅
转载须注明出处:https://www.itshutong.com/articles/1009