Java双重校验锁单例原理

 更新时间:2022年01月21日 11:00:31   作者:让开,我要吃人了  
大家好,本篇文章主要讲的是Java双重校验锁单例原理,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下

前言

作为开发者,单例这个就再也熟悉不过了,但是作为多种单例实现模式,我个人觉得双重校验锁是非常不多的实现,我们简单来分析一下其原理。

正文

先来说一下Java版本的,后面会涉及Kotlin中的代码我们再做比对。

代码实现

Java代码实现如下:

//双重校验锁单例
public class SingleInstance {
    //必须volatile修饰 见分析1
    private volatile static SingleInstance instance;
    //私有化构造函数
    private SingleInstance() {
    }
 
    public static SingleInstance getInstance() {
        //第一个判空 见分析2
        if (instance == null) {
            synchronized (SingleInstance.class) {
                //第二个判空 见分析3
                if (instance == null) {
                    //新建实例
                    instance = new SingleInstance();
                }
            }
        }
        return instance;
    }
}

首先这里synchronized关键字没有修饰整个getInstance函数,因为这个函数可能使用地方很多,这样就会造成其他线程阻塞,不太好,所以这里只同步了一段代码。

分析2:为什么在进入同步代码块时需要进行进行判空,假如有线程A和线程B,这时线程A先判断instance为null,所以它进入了同步代码块,创建了对象,然后线程B再进来时,它就不必再进入同步代码快了,可以直接返回,也其实也就是懒加载,可以加快执行速度。

分析3:为什么在同步代码块中还要再进行一次判断呢,假如有线程A和线程B,它俩A先调用方法,B紧接着调用,这时A、B在分析2出的判空都是空,所以A进入同步代码块,B进行等待,当A进入同步代码块中创建了对象后,A线程释放了锁,这时B再进入,如果这时不加分析3的判空,B又会创建一个实例,这明显不符合规矩。

分析1:那既然加了2层判断,那为什么还要加个volatile关键字呢,这里知识点就有点多了。

因为新建实例的代码:

instance = new SingleInstance();

它不是一个原子操作,这个简单的赋值可以分为3步:

1、给SingleInstance分配内存

2、调用SingleInstance的构造方法

3、把instance指向分配的内存空间

这是正常逻辑的3个步骤,也只有按1 2 3执行后,这个instance才不是null。

但是Java内存模型允许这个进行指令重排序,也就是这3步可能是123也可能是132,所以这里就有问题了。

假如线程A和线程B,线程A已经跑到分析3处的代码,这时这条指令执行是132,刚把步骤3执行完,这时线程B跑到了分析1处的代码,会发现instance不为null了,这时线程B就直接返回了,从而导致错误。

既然知道了原因,那volatile关键字就是解决这个的,它可以禁止指令重新排序,而且保证所有线程看到这个变量是一致的,也就是不会从缓存中读取(这个特性后面有机会再说),所以在创建instance实例时,它的步骤都是123,就不会出错了。

总结

到此这篇关于Java双重校验锁单例原理的文章就介绍到这了,更多相关Java校验锁单例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot的SpringPropertyAction事务属性源码解读

    springboot的SpringPropertyAction事务属性源码解读

    这篇文章主要介绍了springboot的SpringPropertyAction事务属性源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • java Thread 多线程

    java Thread 多线程

    本篇文章小编为大家介绍,java Thread 多线程。需要的朋友参考下
    2013-04-04
  • Java全面解析XML格式串(JDOM解析)

    Java全面解析XML格式串(JDOM解析)

    下面小编就为大家带来一篇Java全面解析XML格式串(JDOM解析)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • Java Swing BoxLayout箱式布局的实现代码

    Java Swing BoxLayout箱式布局的实现代码

    这篇文章主要介绍了Java Swing BoxLayout箱式布局的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • JavaWeb中的路径问题解读

    JavaWeb中的路径问题解读

    这篇文章主要介绍了JavaWeb中的路径问题解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java 中函数 Function 的使用和定义示例小结

    Java 中函数 Function 的使用和定义示例小结

    这篇文章主要介绍了Java 中函数 Function 的使用和定义小结,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • JDK8新特性-java.util.function-Function接口使用

    JDK8新特性-java.util.function-Function接口使用

    这篇文章主要介绍了JDK8新特性-java.util.function-Function接口使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Java线程中卖火车票问题的深入讲解

    Java线程中卖火车票问题的深入讲解

    这篇文章主要给大家介绍了关于Java线程中卖火车票问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • SpringSecurity+JWT实现前后端分离的使用详解

    SpringSecurity+JWT实现前后端分离的使用详解

    这篇文章主要介绍了SpringSecurity+JWT实现前后端分离的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 详解SPI在Dubbo中的应用

    详解SPI在Dubbo中的应用

    通过本文的学习,可以了解 Dubbo SPI 的特性及实现原理,希望对大家的开发设计有一定的启发性
    2021-06-06

最新评论