设计模式——多线程下的懒汉式单例

2023-11-15

"懒汉"模式虽然有优点, 但是每次调用 GetInstance()静态方法时, 必须判断NULL == m_instance, 使程序相对开销增大。多线程中会导致多个实例的产生, 从而导致运行代码不正确以及内存的泄露。

对于多线程的问题,我们可以看下面这个例子:

#include <iostream>
#include <windows.h>
using namespace std;
//懒汉式
class Singleton
{
private:
    Singleton(){
        Sleep(10);
    }
public:
    static Singleton* getInstance(){
        if(sin == NULL)//懒汉式: 1 每次获取实例都要判断 2 多线程会有问题
        {
            sin = new Singleton;
        }
        return sin;
    }
    static void deleteInstance(){
        if(sin != NULL)
        {
            delete sin;
            sin = NULL;
        }
    }
private:
    static Singleton * sin;//未初始化
};
Singleton * Singleton::sin = NULL; 

假设有多线程,第一个线程进入实例化,然后会运行Sleep函数,第二个线程肯定不是等上一个线程Sleep运行完才执行,然而上一个线程没有实例化完成,所以同样会进行实例化,然后运行Sleep,这样的话,等到Sleep运行完,会有多个实例产生。这样单例模式就失去了意义,浪费了开销。

懒汉式遇上多线程,将可能不再是单例。

 

解决方法:Double-Checked Locking(两次检查)

代码如下:

//临界区
static CCriticalSection cs;

static Singleton *Instantialize()
{
    if(pInstance == NULL) //double check
    {
        cs.Lock(); //只有当 pInstance 等于 null 时, 才开始使用加锁机制 二次检查
        if(pInstance == NULL)
        {
            pInstance = new Singleton();
        } 
        cs.Unlock();
    } return pInstance;
} 
static Singleton *pInstance;

解读:这里有一个临界区的概念,若想详细查看,可看操作系统相关。

  1. 若第一个线程进入,第一次判断为空,继续进入,进行加锁,判断为空,继续进入创建实例。
  2. 在第一个线程创建实例过程中,第二个线程也进入到加锁这行代码,犹豫加锁后还没解锁,线程2进入进入阻塞状态等待解锁,同样后面的线程3等也会进入此状态。
  3. 之后,若线程1执行完实例化,解锁,线程2开始执行,但是已经实例化,所以不重新实例化,解锁跳出,之后的线程也是如此。新进入的线程第一次判空便会直接跳出。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式——多线程下的懒汉式单例 的相关文章

  • Spring源码学习之BeanDefinition源码解析

    本文作者 磊叔 GLMapper本文链接 https juejin cn post 6844903553820000269 Bean的定义主要由BeanDefinition来描述的 作为Spring中用于包装Bean的数据结构 今天就来看看
  • 23种设计模式之装饰模式

    装饰模式 一个简陋的房子 它可以让人在里面居住 为人遮风避雨 但如果给它进行装修 那么它的居住环境就更加宜人了 程序中的对象也与房子十分类似 首先有一个相当于 房子 的对象 然后经过不断装饰 不断对其增加功能 它就变成了使用功能更加强大的对
  • 常用设计模式总结

    设计模式的相关知识 很多书籍和博客中都有详细总结 本文总结的目的 1 将自己学习到的设计模式的知识按照自己的逻辑重新总结 方便查看和记忆 2 方便让自己对设计模式中常用的知识有一个系统的认知 设计模式 话设计模式 书中提到 24 种设计模式
  • 离散仿真引擎基础作业与练习

    作业内容 一 简答题 1 解释 GameObjects 和 Assets 的区别与联系 2 下载几个游戏案例 分别总结资源 对象组织的结构 3 使用 debug 验证 MonoBehaviour 基本行为或事件触发条件 4 了解 GameO
  • Java设计模式-装饰者模式Decorator

    介绍 装饰者模式的核心思想是通过创建一个装饰对象 即装饰者 动态扩展目标对象的功能 并且不会改变目标对象的结构 提供了一种比继承更灵活的替代方案 需要注意的是 装饰对象要与目标对象实现相同的接口 或继承相同的抽象类 另外装饰对象需要持有目标
  • C++设计模式-State状态模式

    State状态模式作用 当一个对象的内在状态改变时允许改变其行为 这个对象看起来像是改变了其类 UML图如下 State类 抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为 ConcreteState类 具体状态 每一
  • 程杰“大话设计模式”中的设计原则

    单一职责原则 SRP 就一个类而言 应该仅有一个引起它变化的原因 如果一个类承担的职责过多 就等于把这些职责耦合在了一起 一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力 这种耦合会导致脆弱的设计 当发生变化时 设计会遭受到意想不到
  • 设计模式七大原则

    1 设计模式的目的 编写软件过程中 程序员面临着来自耦合性 内聚性以及可维护性 可扩展性 重用性 灵活性 等多方面的挑战 设计模式是为了让程序 软件 具有更好 1 代码重用性 即 相同功能的代码 不用多次编写 2 可读性 即 编程规范性 便
  • Tomcat 系统架构与设计模式之工作原理篇

    本文以 Tomcat 5 为基础 也兼顾最新的 Tomcat 6 和 Tomcat 4 Tomcat 的基本设计思路和架构是具有一定连续性的 Tomcat 总体结构 Tomcat 的结构很复杂 但是 Tomcat 也非常的模块化 找到了 T
  • [C++]外观模式

    外观模式 Facade Pattern 隐藏系统的复杂性 并向客户端提供了一个客户端可以访问系统的接口 这种类型的设计模式属于结构型模式 它向现有的系统添加一个接口 来隐藏系统的复杂性 这种模式涉及到一个单一的类 该类提供了客户端请求的简化
  • DDD专家张逸:构建领域驱动设计知识体系

    张逸 读完需要 5分钟 速读仅需 2 分钟 领域驱动设计专家 曾就职于 ThoughtWorks 作为 Lead Consultant 为客户提供架构设计 大数据分析 持续交付 代码质量 敏捷管理等咨询服务 著译作包括 软件设计精要与模式
  • 组合型模式

    概述 对于这个图片肯定会非常熟悉 上图我们可以看做是一个文件系统 对于这样的结构我们称之为树形结构 在树形结构中可以通过调用某个方法来遍历整个树 当我们找到某个叶子节点后 就可以对叶子节点进行相关的操作 可以将这颗树理解成一个大的容器 容器
  • 设计模式(2)

    2 2 结构型模式 结构型模式一共有七种 其中 适配器模式和装饰模式统称为包装模式 装饰模式和代理模式的类图基本相同 但目的不同 这些有相似目的或者有相似结构的模式需要对其概念辨析清楚 才能较好地掌握 下面将对结构型模式分别进行介绍 2 2
  • 二十四种设计模式之策略模式

    一 什么是策略模式 简单来说 策略模式是将每一个算法封装到拥有共同接口的不同类中 使得算法可以在不影响客户端的情况下发生变化 也可以理解为可供程序运行时选择的 不同的类 不同的解决方案 策略模式的特点 高内聚低耦合 可扩展 遵循ocp原则
  • 在AI技术的无情侵袭下,学学Java的23种设计模式还是非常有必要的

    目前国内80 程序员的主要工作是调用组合api实现各种业务需求 在顶层架构师设定好的框架下 做着重复且无聊的编码工作 如果未来ai被广泛应用 那么被替代的风险是很高的 比较扎心的是 其实目前用ai生成片段代码已经是各个公司比较普遍的做法了
  • Java设计模式:模板方法模式

    作者主页 欢迎来到我的技术博客 个人介绍 大家好 本人热衷于 Java后端开发 欢迎来交流学习哦 如果文章对您有帮助 记得 关注 点赞 收藏 评论 您的支持将是我创作的动力 让我们一起加油进步吧 文章目录 一 模板方法模式的定义 二 模板方
  • 设计模式(3)--对象结构(5)--外观

    1 意图 为子系统中的一组接口提供一个一致的界面 Facade模式定义了一个高层接口 这个接口使得 这一子系统更加容易使用 2 两种角色 子系统 Subsystem 外观 Facade 3 优点 3 1 对客户屏蔽了子系统组件 减少了客户处
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • 【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

    文章目录 一 进行面向对象设计 1 划分职责 gt 需要有哪些类 2 定义类及其属性和方法 3 定义类与类之间的交互关系 4 将类组装起来并提供执行入口 二 如何进行面向对象编程 1 接口实现
  • 系列一、 单例设计模式

    一 单例设计模式 1 1 概述 单例模式 Singleton Pattern 是Java中最简单的设计模式之一 这种类型的设计模式属于创建者模式 它提供了一种创建对象的最佳方式 这种模式涉及到一个单一的类 该类负责创建自己的对象 同时确保只

随机推荐