C++ 单例模式

懒汉模式

  1. 在多线程情况下,懒汉模式是线程是不安全的,如果多个线程同时去访问单例对象,而这个单例对象尚未初始化,那么在判断 instance == nullptr 的时候,可能会出现 instance 已经在创建了,但是判断结果还是为true,就会创建出多个单例对象的实例;

解决方案:使用双检查锁;使用静态局部变量也可以解决;

为什么要两次判断 instance == nullptr 之后,才初始化单例对象?

假设此时单例对象还没有创建,有两个线程同时进入单例对象的访问函数,此时两个线程都通过的第一次为空的判断,在两次判断之间有一把互斥锁,只有一个线程可以获取,该线程获取后,第二次判断为空,开始初始化单例对象,初始化结束后释放锁;此时另一个线程进入第二次为空判断,发现单例对象已经初始化;通过双检查锁的机制,可以避免线程安全问题;

为什么互斥锁在两次检查之间获取,而不是在第一次检查开始前直接获取?

如果放在第一次检查前,那么每次获取单例对象,都要先获取互斥锁,会带来极大的资源浪费;

  1. 单例模式的默认构造函数需要设置为private,且拷贝构造函数和 "=" 赋值运算符都要禁用;

单例模式的默认构造函数设置为private是为了防止构造函数被外部调用,如果外部可以调用单例类的构造函数,那么这就不会仅存在一个单例;

禁用拷贝构造函数和 "=" 赋值运算符也是同理,反之单例类对象被多次创建;

cpp 复制代码
// 线程安全的懒汉模式
#include <mutex>

class SingleClass {

public:
    SingleClass(const SingleClass&) = delete;
    SingleClass& operator=(const SingleClass&) = delete;

    static SingleClass *getInstance() {
        if (instance == nullptr) {
            m_mutex.lock();
            if (instance == nullptr) {
                instance = new SingleClass();
            }
            m_mutex.unlock();
        }
        return instance;
    }

private:
    static SingleClass *instance;
    static std::mutex m_mutex;

    SingleClass() = default;
    
};

// 静态变量需要在类内声明,在类外初始化
SingleClass *SingleClass::instance = nullptr;
std::mutex SingleClass::m_mutex;

饿汉模式

  1. 与懒汉模式的区别就在于,在程序启动时,或在类加载时编译期,就将单例类实例化,所以不需要双检查锁,也就不存在线程安全问题;在获取单例实例的时候,直接return instance 即可。
相关推荐
Y.O.U..3 分钟前
今日八股——C++
开发语言·c++·面试
Zhichao_9740 分钟前
【UE5 C++课程系列笔记】33——商业化Json读写
c++·ue5
云边有个稻草人1 小时前
【C++】第八节—string类(上)——详解+代码示例
开发语言·c++·迭代器·string类·语法糖auto和范围for·string类的常用接口·operator[]
惊鸿一博1 小时前
c++ &&(通用引用)和&(左值引用)区别
开发语言·c++
高 朗2 小时前
2025高频面试设计模型总结篇
设计模式·面试·职场和发展
nuo5342022 小时前
黑马 C++ 学习笔记
c语言·c++·笔记·学习
DARLING Zero two♡2 小时前
C++类间的 “接力棒“ 传递:继承(上)
开发语言·c++·继承·里氏替换原则
会讲英语的码农2 小时前
如何学习C++以及C++的宏观认知
开发语言·c++·学习
Merokes10 小时前
关于Gstreamer+MPP硬件加速推流问题:视频输入video0被占用
c++·音视频·rk3588
请来次降维打击!!!11 小时前
优选算法系列(5.位运算)
java·前端·c++·算法