美文网首页学习之Java学习
单例模式-懒汉式-Java双重校验锁🔒

单例模式-懒汉式-Java双重校验锁🔒

作者: 千夜零一 | 来源:发表于2021-06-07 17:56 被阅读0次

单例模式

饿汉式:

public class SingletonE {

    /**
     * ----饿汉式----
     * 是否 Lazy 初始化:否
     * 是否多线程安全:是
     * 实现难度:易
     */
    private static SingletonE instance = new SingletonE();
    private SingletonE(){}
    public static SingletonE getInstance(){
        return instance;
    }
}

懒汉式:

public class SingletonL {
    private static SingletonL instance;
    private SingletonL(){ }

    /**
     * <==="懒汉式"===>
     * 是否 Lazy 初始化:是
     * 是否多线程安全:否
     * 实现难度:易
     */
//    public SingletonL getInstance(){
//        if (null == instance){
//            instance = new SingletonL();
//        }
//        return instance;
//    }

    /**
     * <==="懒汉式"-线程安全===>
     * 是否多线程安全:是
     * 实现难度:易
     * 缺点:线程安全了,但每次实例化需要检查锁,性能低。
     */
//    public static synchronized SingletonL getInstance() {
//        if (null == instance){
//            instance = new SingletonL();
//        }
//        return instance;
//    }
}

双重校验锁🔒

public class SingletonDCL {
    /**
     * <==="懒汉式"--双重校验锁--===>
     * JDK 版本:JDK1.5 起
     * 是否 Lazy 初始化:是
     * 是否多线程安全:是
     * 实现难度:较复杂
     */

    private static volatile SingletonDCL instance;
    private SingletonDCL(){}

    public static  SingletonDCL  getInstance() {
        if(null == instance){
            synchronized (SingletonDCL.class){
                if(null == instance){
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
    /**
     * 相关问题:
     1、为什么synchronized关键字要放在SingletonDCL getInstance()方法内?
     2、为什么要在synchronized修饰代码段内再次加校验?
     3、为什么要对SingletonDCL.class加锁,而不是局部变量?
     4、为什么要使用volatile关键字修饰instance变量?
     5、双重校验锁第一次进行判空原因?
     6、双重校验锁第二次进行判空原因?
     */
}

问题解惑:

  • 1、为什么synchronized关键字要放在SingletonDCL getInstance()方法内?

    答:对比《单例-懒汉式》线程安全的写法,之前为了解决了线程安全问题,采用synchronized关键字放在getInstance之前

    public static synchronized SingletonL getInstance() {……}
    

    这样的是可以解决线程安全问题,但因为每次调用getInstance()方法都需要检查锁🔒,性能低。

    因此,需要在没有初始化实例(instance=null)之前,对未初始化的对象加锁校验;第二次调用getInstance获取单例的时候,如果对象已被实例化,不会再校验锁。性能优化了~

  • 2、为什么要在synchronized修饰代码段内再次加校验?

答:由于synchronized加在了getInstance方法内,因此导致线程不安全了,若要使线程安全,需要在synchronized修饰的代码块内再次进行if(null == instance){}校验,保证线程安全。

  • 3、为什么要对SingletonDCL.class加锁,而不是局部变量?

答:首先要明确的一个点,就是synchronized关键字可以修饰什么?变量、代码块段、方法、对象。都可以,因为A线程、B线程其实都是对这个单例类进行访问,因此需要锁的是这个类对象!

  • 4、为什么要使用volatile关键字修饰instance变量?

答:首先明确一个点:不加volatile线程就不安全了吗?当然不是,无论加不加volatile关键字,此时线程都是安全的,并且性能也高!那为什么要加volatile呢?禁止指令重排序!不被volatile修饰前,代码的执行顺序可能会改变,但被修饰之后,指令重排序被禁止。

  • 5、双重校验锁第一次进行判空原因?

    答:如果不进行判空,每个线程都会去获取这个当前类的类锁,而其他线程都进入阻塞状态。单例模式中初始化单例的程序只会执行一次,大部分情况下会直接到return语句返回,如果都阻塞在获取锁的位置,会大大降低程序的运行速度。

  • 6、双重校验锁第二次进行判空原因?

答:假设有两个线程A和B,都进行完第一次判空了,A和B都阻塞在synchronized (SingletonDCL.class){……}之前。因此需要二次判空,防止阻塞。

相关文章

  • Kotlin 的单例模式

    Kotlin 的单例模式(5种) Kotlin 的5种单例模式: 饿汉式 懒汉式 线程安全的懒汉式 双重校验锁式 ...

  • 每天一个设计模式

    1.单例模式 懒汉式,线程不安全 懒汉式,线程安全 饿汉式 双检锁/双重校验锁(DCL,即 double-chec...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • 单例模式

    单例模式 单例模式简介基本用法Kotlin 不带参Kotlin 带参饿汉式懒汉式双重校验锁静态内部类枚举集合管理问...

  • 2018-05-14

    单利设计模式 懒汉式 单例模式 饿汉式 单利模式 懒汉式与饿汉式的区别: 双重锁式 单例模式 (DCL )

  • 单例模式-懒汉式-Java双重校验锁🔒

    单例模式 饿汉式: 懒汉式: 双重校验锁? 问题解惑: 1、为什么synchronized关键字要放在Single...

  • 单例模式(kotlin实现)

    Java 实现 饿汉式 懒汉式 线程安全的懒汉式 双重校验锁式(Double Check) 静态内部类式 双重校验...

  • Kotlin设计模式(1)单例模式

    饿汉模式懒汉模式线程安全的懒汉模式双重校验锁的懒汉模式静态内部类的懒汉模式   单例模式是开发中最常用的设计模式,...

  • 深入理解单例模式

    前言 ​ 单例模式有很多种形式:饿汉式、懒汉式、DCL(双重校验)、静态内部类、容器单例、ThreadLoca...

  • 高级 Java 面试通关知识点整理!

    1、常用设计模式 单例模式:懒汉式、饿汉式、双重校验锁、静态加载,内部类加载、枚举类加载。保证一个类仅有一个实例,...

网友评论

    本文标题:单例模式-懒汉式-Java双重校验锁🔒

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