简单的单例模式

xiaoxiao2025-10-26  13

/** 一个简单的懒汉式单例模式出现的问题及解决方案 */ #include <iostream> #include <thread> #include <mutex> #define THREAD_NUM 10 using namespace std; class Singleton { public: //12.此处加一个垃圾清理类就可以实现程序退出前调用Singleton的析构函数了 class Garbo { public: ~Garbo() { if (nullptr != mInstance) { delete mInstance; } } }; //3.为了能够在类外使用对象,所以需要提供一个成员函数用来使对象能够 //在类外使用,由于其他函数不能够直接用类名访问成员函数,而单例又不能在类外 //产生对象来调用类的相关成员函数,所以这里用静态成员函数以供类外访问唯一实例 static Singleton* getInstance() { //4.由于懒汉式是使用的时候产生对象,所以需要先new一个对象,由于只能使 //其产生一次,所以这里需要引入第一重判断 //7.由于多线程问题,这里考虑加锁,加锁后能产生单个实例对象了,但是引入 //频繁加锁和解锁的开销,导致程序执行效率不够理想 //9.为了不让每个线程执行时都进入加锁状态,这里需要引入双重判定,使其只有 //进入加锁状态,减少系统开销 //10.要让对象在进程结束前执行析构函数又需要怎么弄? //可以引入一个垃圾清理类Garbo if (nullptr == mInstance) { //mInstanceMutex.lock(); lock_guard<mutex> guard(mInstanceMutex); //13.问题又出现了,如果在加锁和解锁这段程序中间需要进行错误处理, //抛出异常,程序就会出现死锁,怎么解决,思路是利用局部变量的作用域 //在{},也就是在括号结束对象会调用其析构函数,将锁换成门卫类 if (nullptr == mInstance) { mInstance = new Singleton(); throw 1; } //mInstanceMutex.unlock(); } return mInstance; } private: //1.为了只能产生一个对象,所以不能让其能在类外产生对象,所以需要先私有化 //其默认构造函数和默认拷贝构造函数,如果是C++11还需要将其移动构造函 //数私有化 Singleton() { cout << "Singleton Constructor!" << endl; } Singleton(const Singleton &singleton) { cout << "Singleton Copy Constructor!" << endl; } Singleton(const Singleton &&sigleton) { cout << "Singleton Move Constructor!" << endl; } ~Singleton() { cout << "Singleton Destructor!" << endl; } //2.由于类外不能产生对象,所以需要在类内构造一个类外全局能够访问的对象 //(静态变量的生命周期可以胜任此需求);可以有两种方式,一种方式是直接在类 //内定义一个对象,比较简单,另一种方式是在类内定义一个指针,此种情况下分 //为懒汉式和饿汉式两种模式,由于懒汉式问题较多,故而这里只写懒汉式 static Singleton *mInstance; //8.由于要加锁,先定义一个静态的互斥量 static mutex mInstanceMutex; //11.定义Garbo类型的静态成员,由于进程结束会调用其析构函数,所以可以 //实现在进程结束前释放掉单例对象 static Garbo mGarbo; }; //注意:*写在mInstance前Singleton后编译会产生链接错误, Singleton *Singleton::mInstance = nullptr; mutex Singleton::mInstanceMutex; Singleton::Garbo Singleton::mGarbo; void fun(int num) { try { //cout << num << endl; //6.在每个线程中使用懒汉式产生出来的实例 //这样在多线程中会产生多个实例,不符合单例模式,解决方式可以考虑加锁 Singleton::getInstance(); } catch (...) { } } int main() { //5.创建多个线程来测试懒汉式单例模式的问题 thread *arr[THREAD_NUM] = { nullptr }; for (int i = 0; i < THREAD_NUM; i++) { //new出所有线程 arr[i] = new thread(fun, i); } for (int i = 0; i < THREAD_NUM; i++) { //等待所有线程结束,回收资源 arr[i]->join(); } for (int i = 0; i < THREAD_NUM; i++) { delete arr[i]; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-5038551.html

最新回复(0)