美文网首页
设计模式之单例:线程安全、性能、可读不能兼得吗?

设计模式之单例:线程安全、性能、可读不能兼得吗?

作者: 请给我一根烟的时间 | 来源:发表于2022-05-06 00:55 被阅读0次

有的情况下,我们只需要创建一个实例,以此来节省创建和销毁的消耗,以及保持该实例的稳定性(不希望被外部破坏或篡改)

此时我们可以应用单例模式来创建该实例的对象,下面列举几种方法,并且说明其各自的使用场景和优缺点:

饿汉模式

顾名思义,我很饥饿,我上来就创建该实例,不惯用不用得着,并且以后都使用该实例。示例代码:
关键代码说明:
构造器是私有的,这样就避免了被外部实例化
属性加上final属性之后,也可以避免被再次赋值,而像通过下面的静态代码块来初始化,就不能加上final修饰符来限制

懒汉模式 - 双重锁

饿汉模式比较简单,但是有的时候实例化一次资源如果消耗很大的话,我们就希望在对象被实际使用到(调用)的时候才进行实例化,我们很容易想到下面的代码实现:

看起来似乎不错,但在并发多线程场景下,进行对象实例化的代码INSTANCE = new Mgr();是有可能被同时执行到的,这样一来,就不满足单例的要求了。
怎么办呢?熟悉多线程的工程师会给这个实例化方法加上一个锁来解决这个问题,像下面这样:
开启多个线程测试也能通过,但仍然有缺陷,因为加锁就以为着,这个方法被所有线程一个一个的排队去使用,多线程失去了意义,性能损失很大。

接着往下想,怎么办?能不能在需要进行实例化的代码块上进行精准加锁呢?像下面这样
这样是不是就完美了?实际还有问题的,如果多个线程同时执行了代码if(INSTANCE == null) 并且都等待锁去做对象实例化,就还会new出来多个实例。于是,下面就引出了经典的双重锁方式
这样一来,即便是有多个线程拿到了锁要去做对象的实例化,还会再次检查一下对象是否为空才会执行实例化逻辑。因为第一个拿到锁线程一定已经完成了对象的实例化,其他拿到锁的线程检查if(INSTANCE == null)的时候就一定是false了。

懒汉模式 - 静态内部类

在Effective Java这本书中,作者提到了更为简洁的时间懒汉模式的方法——通过静态内部类。我们将上述代码改造一下
看起来简洁多了。但是稍微难理解一点,这利用了JVM类加载的机制,在加载类的时候,静态内部类MgrHelpler会被加载,但内部的静态属性 INSTANCE 只有在被使用到的时候,才会被实例化,后续再调用就直接使用该实例了。
懒汉模式 - 枚举属性

还有一种预发层面天然支持,就是枚举,枚举的构造器默认就是private的,因此可以很好的避免外部的篡改,另外枚举的属性只有在使用到时候,才会进行初始化,因而也可以避免使用前的资源消耗。上面的代码可以修改为以下简单的几行
so easy,当然实际场景实例化过程会添加到构造器当中。

总结

上面介绍了4种可行的构建单例的模式:
1. 饿汉模式
2. 懒汉模式 - 双重锁
3. 懒汉模式 - 静态内部类
4. 懒汉模式 - 枚举属性

一般来讲,没有特殊的考虑,使用饿汉模式即可,简单易于理解,如果处于性能考虑,3中懒汉模式可以根据实际情况进行使用。

————————————————
笔者原文发布在CSDN,欢迎点击查看:https://blog.csdn.net/mytream/article/details/124601090

也可以关注博客(请给我一根烟的时间https://blog.csdn.net/mytream),查看更多个人心得和分享

相关文章

  • 设计模式之单例:线程安全、性能、可读不能兼得吗?

    有的情况下,我们只需要创建一个实例,以此来节省创建和销毁的消耗,以及保持该实例的稳定性(不希望被外部破坏或篡改)此...

  • Unity3d游戏开发之-单例设计模式- 单例模式二:多线程二(

    单例模式4:多线程二(双重锁定)这种双重锁定考虑了线程安全,是正规写法 游戏常用设计模式之单例设计模式的写法大概常...

  • 设计模式

    手写单例模式(线程安全) 你知道几种设计模式?单例模式是什么?Spring中怎么实现单例模式?

  • Java 单例模式

    概述 Java中单例模式是一种常见的设计模式,单例模式总共有7种写法。 懒汉,线程不安全 懒汉,线程安全 饿汉 饿...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • 关于单例模式的思考

    饿汉式单例模式(写法一) /** * 饿汉式单例 写法一 * 优点:简单,性能高,线程安全 * 缺点:浪费内存(当...

  • 单例模式的常用实现方式

    单例模式属于最常用的设计模式,Java中有很多实现单例模式的方式,各有其优缺点 实现方式对比 单例实现方式线程安全...

  • 单例

    单例,是Java中很重要的一个设计模式。 实现单例是要考虑并发(线程安全)问题的。 如何实现一个线程安全的单例?你...

  • C++中线程安全的单例模式

    简介 单例模式是很常用的一种设计模式,在实现过程中要非常注意线程安全,我们会介绍四种方式来实现线程安全的单例模式:...

  • 单例模式

    安卓常用的设计模式 单例模式的6种写法: 饿汉模式,懒汉模式(线程不安全),懒汉模式(线程安全),双重检查模式(D...

网友评论

      本文标题:设计模式之单例:线程安全、性能、可读不能兼得吗?

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