首页 > 其他分享 >单例模式

单例模式

时间:2023-04-01 20:45:10浏览次数:39  
标签:taskQ const 模式 TaskQueue mutex 单例 static delete

单例模式

在全局范围中,某个类的对象只有一个,通过这个唯一的实例向其他模块提供数据的全局访问。

需要:

  • 默认构造函数私有化
    • 因为使用者在类外部无法创建类对象,故在类内创建静态对象通过类名来访问
    • 在类中只有静态成员函数才能访问静态成员变量,故提供一个静态成员函数提供该静态对象
  • 拷贝构造函数私有化或禁用
  • 拷贝复制运算符私有化或禁用

饿汉模式

在类加载时立即实例化,无线程安全问题

class TaskQueue {
public:
    TaskQueue(const TaskQueue &t) = delete;
    TaskQueue &operator=(const TaskQueue &t) = delete;
    
    static TaskQueue *get_instance() { return m_taskQ; }
private:
    TaskQueue() = default;
    
    static TaskQueue *m_taskQ;
};

TaskQueue *TaskQueue::m_taskQ = new TaskQueue;

int main()
{
    TaskQueue *t = TaskQueue::get_instance();
}

懒汉模式

在加载时不创建唯一实例,直到使用才创建,有线程安全问题

class TaskQueue {
public:
    TaskQueue(const TaskQueue &t) = delete;
    TaskQueue &operator=(const TaskQueue &t) = delete;
    
    static TaskQueue *get_instance() {
        if (m_taskQ == nullptr) {
            m_taskQ = new TaskQueue;
        }
        return m_taskQ;
    }
private:
    TaskQueue() = default;
    
    static TaskQueue *m_taskQ;
};

TaskQueue *TaskQueue::m_taskQ = nullptr;

线程安全问题处理

双重检查锁定

class TaskQueue {
public:
    TaskQueue(const TaskQueue &t) = delete;
    TaskQueue &operator=(const TaskQueue &t) = delete;
    
    static TaskQueue *get_instance() {
        if (m_taskQ == nullptr) {
            m_mutex.lock();
        	if (m_taskQ == nullptr) {
            	m_taskQ = new TaskQueue;
        	}
        	m_mutex.unlock();
        }
        return m_taskQ;
    }
private:
    TaskQueue() = default;
    
    static TaskQueue *m_taskQ;
    static mutex m_mutex;
};

TaskQueue *TaskQueue::m_taskQ = nullptr;
mutex TaskQueue::m_mutex;

上述代码在 m_taskQ = new TaskQueue 处由于机器指令重排加上恰好时间片结束,仍然会出现线程安全问题

class TaskQueue {
public:
    TaskQueue(const TaskQueue &t) = delete;
    TaskQueue &operator=(const TaskQueue &t) = delete;
    
    static TaskQueue *get_instance() {
        TaskQueue *queue = m_taskQ.load();
        if (queue == nullptr) {
            lock_gard<mutex> locker(m_mutex);
            queue = m_taskQ.load();
            if (queue == nullptr) {
                queue = new TaskQueue;
                m_taskQ.store(queue);
            }
        }
        return queue;
    }
private:
    TaskQueue() = default;
    
    static atomic<TaskQueue *> m_taskQ;
    static mutex m_mutex;
};

atomic<TaskQueue *> TaskQueue::m_taskQ;
mutex TaskQueue::m_mutex;

静态局部对象

class TaskQueue {
public:
    TaskQueue(const TaskQueue &t) = delete;
    TaskQueue &operator=(const TaskQueue &t) = delete;
    
    static TaskQueue *get_instance() {
        static TaskQueue taskQ;
        return &taskQ;
    }
private:
    TaskQueue() = default;
};

标签:taskQ,const,模式,TaskQueue,mutex,单例,static,delete
From: https://www.cnblogs.com/cong0221/p/17279310.html

相关文章

  • 谈谈Spring中都用到了哪些设计模式?
    ​ 控制反转(IOC)和依赖注入(DI)IoC(InversionofControl,控制翻转) 是Spring中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想。它的主要目的是借助于“第三方”(即Spring中的IOC容器)实现具有依赖关系的对象之间的解耦(IOC容易管理对象,你只管使用即可),从而......
  • 谈谈Spring中都用到了哪些设计模式?
    ​ 控制反转(IOC)和依赖注入(DI)IoC(InversionofControl,控制翻转) 是Spring中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想。它的主要目的是借助于“第三方”(即Spring中的IOC容器)实现具有依赖关系的对象之间的解耦(IOC容易管理对象,你只管使用即可),从而......
  • 3.优化器模式的选择
    1优化器的模式1.1.RULE模式  Oracle将使用RBO来解析目标SQL,统计信息将失去作用1.2.CHOOSE模式  Oracle9i中OPTIMIZER_MODE的默认值,表示Oracle在解析目标SQL到底使用RBO还是CBO,如果该SQL涉及的表存在统计信息,Oracle解析SQL就会使用CBO,如果所有表对象没有统计信息,用RBO......
  • 单例模式的运用
    (1)案例背景:在实际的运用中,我们有时一个类不止需要产生一个对象,可能需要两个或者三个。在课上我们讲过,使用单例模式的思想可以实现多例模式,从而确保系统中某个类的对象只能存在有限个,请设计并实现代码,从而实现多例模式(2)实现步骤:由于本题的实现较为复杂,所以我们直接给出参考类图......
  • IWDG-CH32FV2x_V3x--低功耗模式的看门狗处理
    芯片睡眠模式下看门狗的使用:     由于独立看门狗的特殊性,一旦开启就不能再被关闭,除非发生复位。而睡眠时程序又是停止运行的,这样就无法及时喂狗,从而导致看门狗复位。那么就需要软件上做些特殊   处理     方法1:在低功耗模式下进行RTC定时唤醒CPU进行......
  • 代理模式 Proxy
    代理类模式在不改变原有类的基础上,代理一个类,并对其方法前后进行增强1.Java动态代理:代理实现某一个接口的类或接口本身接口类publicinterfaceBody{voiddoThing();}实现类:publicclassPersonimplementsBody{@OverridepublicvoiddoThing(){......
  • 企业实践 | 如何在阿里云裸金属服务器上使用UEFI模式实践安装国产银河麒麟V10操作系统
    [点击......
  • 解释器模式(Interpreter Pattern)
    一、概念解释器模式(InterpreterPattern)用于构造一个简单的语言解释器,将字符串按照自定义的方式解释执行,是一种不常用的设计模式除非从事底层开发自己需要去定义较为复杂的表达式,否则基本上不同这个设计模式二、适用场景(1)当一个语言需要解释执行,并可以将该语言中的句子......
  • 单例的各种方式实现,本写法以类A为例,泛型可以使用T
    单例的使用如下:#region单例的各种方式实现,本写法以类A为例,泛型可以使用TpublicclassA{#region单线程----常规,多线程不安全/////<summary>/////私有构造函数,防止初始化/////</summary>//privateA()//{......
  • 命令模式
    概述《设计模式》一书中对于“命令模式”的意图描述如下:将一个请求封装成为一个对象,从而可以使用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作一般“命令模式”的UML图如下所示:一般会在以下几种情况下使用命令模式:需要抽象出待执行的......