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

先看双重校验锁的写法

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 操作,这里就出现了第二个类实例,违背了单例原则。

相关推荐
Dylan的码园10 小时前
深入浅出Java排序:从基础算法到实战优化(下)
java·算法·排序算法
中二病码农不会遇见C++学姐10 小时前
文明6 Mod制作核心组件关系解密:从XML到游戏的奇幻漂流
java·运维·服务器·游戏
我爱娃哈哈10 小时前
SpringBoot + ResponseBodyEmitter 实时异步流式推送:告别轮询,让数据推送更高效
java·spring boot·后端
白宇横流学长10 小时前
基于 SpringBoot 的足球俱乐部管理系统设计与实现【源码+文档】
java·spring boot·后端
电商API&Tina10 小时前
唯品会获得vip商品详情 API 返回值说明
java·大数据·开发语言·数据库·人工智能·spring
白宇横流学长10 小时前
基于Spring Boot的连锁电影院管理系统的设计与实现
java·spring boot·后端
码农水水10 小时前
从 OpenFeign 到 RestClient:Spring Cloud 新时代的轻量化 HTTP 调用方案
java·运维·后端·spring·http·spring cloud·面试
小码过河.10 小时前
设计模式——迭代器模式
设计模式·迭代器模式
晔子yy10 小时前
聊聊Java的内存模型
java·开发语言
爱学习的阿磊10 小时前
Python深度学习入门:TensorFlow 2.0/Keras实战
jvm·数据库·python