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 即可。
相关推荐
咩咦1 小时前
C++学习笔记28:静态成员应用:不用循环求1到n的和
c++·学习笔记·类和对象·static·构造函数·oj·静态成员
EllinY1 小时前
CF2217E Definitely Larger 题解
c++·笔记·算法·构造
筠筠喵呜喵2 小时前
Linux软件开发性能优化
linux·c++·性能优化
Bruce_kaizy3 小时前
c++ linux环境编程——文件io介绍以及open 、write 、read 三剑客深度详解
linux·服务器·c++·ubuntu·操作系统·文件io
PAK向日葵5 小时前
我用 C++ 写了一个轻量级 Python 虚拟机,刚刚开源
c++·python·开源
玖釉-5 小时前
下一个排列:从字典序到原地算法的完整推导
数据结构·c++·windows·算法
枕星而眠5 小时前
数据结构八大排序详解(一):四大简单排序
c语言·数据结构·c++·后端
努力努力再努力wz6 小时前
【Qt入门系列】:按钮组件全解析:从 QAbstractButton 到快捷键事件、单选与复选机制
c语言·开发语言·数据结构·c++·git·qt·github
yunn_6 小时前
单例模式两种实现方法
开发语言·c++·单例模式
sinat_255487817 小时前
IDEA:查找文件/类
java·ide·设计模式·intellij-idea