写了一个简单的单例模式分享
/**一个简单的懒汉式单例模式出现的问题及解决方案
*/
#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 = { nullptr };
for (int i = 0; i < THREAD_NUM; i++)
{
//new出所有线程
arr = new thread(fun, i);
}
for (int i = 0; i < THREAD_NUM; i++)
{
//等待所有线程结束,回收资源
arr->join();
}
for (int i = 0; i < THREAD_NUM; i++)
{
delete arr;
}
return 0;
}
有点看不懂,这里是学到c++哪里才能知道这些?
页:
[1]