单例设计模式双重检查的作用

先看双重校验锁的写法

java 复制代码
public class Singleton {

    /*
        volatile 修饰,
        singleton = new Singleton() 可以拆解为3步:
        1、分配对象内存(给singleton分配内存)
        2、调用构造器方法,执行初始化(调用 Singleton 的构造函数来初始化成员变量)。
        3、将对象引用赋值给变量(执行完这步 singleton 就为非 null 了)。
        若发生重排序,假设 A 线程执行了 1 和 3 ,还没有执行 2,B 线程来到判断 NULL,B 线程就会直接返回还没初始化的 instance 了。

        volatile 可以避免重排序。
     */
    private volatile static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

为什么要进行两次非空校验?

第一个 if 判断是为了减少性能开销,不用走 synchronized 代码,避免多余的加锁操作,以及锁的等待和竞争

第二个 if 判断是为了避免生成多个对象实例。比如在未创建实例的情况下,A线程和B线程都通过了第一次校验,这时如果通过竞争B线程拿到了锁就会执行一次 new 操作,生成一个实例,然后 B 执行完了 A 就会拿到资源的锁,如果没有第二次判断的话,这时A线程也会执行一次 new 操作,这里就出现了第二个类实例,违背了单例原则。

相关推荐
Hello.Reader1 小时前
Data Sink定义、参数与可落地示例
java·前端·网络
2401_837088502 小时前
stringRedisTemplate.opsForHash().entries
java·redis
lkbhua莱克瓦244 小时前
Java基础——集合进阶3
java·开发语言·笔记
蓝-萧4 小时前
使用Docker构建Node.js应用的详细指南
java·后端
多喝开水少熬夜4 小时前
Trie树相关算法题java实现
java·开发语言·算法
执笔论英雄4 小时前
【大模型训练】加载load_state 中的一些技巧 工厂设计模式
设计模式
lkbhua莱克瓦245 小时前
Java基础——集合进阶用到的数据结构知识点1
java·数据结构·笔记·github
音符犹如代码6 小时前
Java并发List实战:CopyOnWriteArrayList原理与ArrayList常见面试题
java·开发语言·面试·list
代码or搬砖6 小时前
Docker 部署 Java 项目实践
java·docker·容器
又是忙碌的一天6 小时前
抽象类和接口
java·开发语言