美文网首页
java懒汉式单例为什么是两次非空校验?

java懒汉式单例为什么是两次非空校验?

作者: 放羊娃华振 | 来源:发表于2022-09-05 22:54 被阅读0次

    最近被问到单例为什么一定要进行两次非空的判断?我当时大脑就不转了!晚上我围着小区散散步忽然想起了这个问题,我静静的思考了下,其实我是能答的,但是当时头昏脑涨的就一下乱套了,所以遇到事情还是不要慌,先梳理下基础知识冷静的分析下。

    首先我们看看单例双重检验的代码实现:

    public class SingleInstance {
        private static volatile SingleInstance instance;
        private SingleInstance() {
        }
        public static SingleInstance getInstance() {
            if (instance == null) { //第一层
                synchronized (SingleInstance.class) {
                    if (instance == null) {  //第二层
                        instance = new SingleInstance();
                    }
                }
            }
            return instance;
        }
    }
    

    getInstance()方法第一层非空判断其实就是使用缓存的思想,过滤掉重复竞争锁的逻辑。我们不妨去掉这行代码:

    public class SingleInstance {
        private static volatile SingleInstance instance;
        private SingleInstance() {
        }
        public static SingleInstance getInstance() {
                synchronized (SingleInstance.class) {
                    if (instance == null) {
                        instance = new SingleInstance();
                    }
                }
            return instance;
        }
    }
    

    这是不是就一目了然了,要是没有第一次非空判断,每次都会走竞争锁的逻辑,也是不必要的资源开销。

    再讨论下getInstance()方法的第二层非空判断,它的作用就是阻止多线程的情况下重复创建实例对象。我们不妨去掉这行代码:

    public class SingleInstance {
        private static volatile SingleInstance instance;
        private SingleInstance() {
        }
        public static SingleInstance getInstance() {
            if (instance == null) {
                synchronized (SingleInstance.class) {
                    instance = new SingleInstance();
                }
            }
            return instance;
        }
    }
    

    此时可以看出要是多线程的情况下,多个线程都走到了竞争锁的位置,当第一个线程执行完后释放锁,另外的线程拿到锁还能继续创建对象,此处加了一层非空判断就是规避了此问题。

    相关文章

      网友评论

          本文标题:java懒汉式单例为什么是两次非空校验?

          本文链接:https://www.haomeiwen.com/subject/mmewnrtx.html