C++ 饿汉式单例模式_双重锁
1、单例模式定义
保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局 访问方法。 (GoF给出单例模式的定义)
2、单例模式三个要点
(1)某个类只能有一个实例;
(2)它必须自行创建这个实例;
(3)它必须自行向整个系统提供这个实例
在单例类的内部实现只生成一个实例,同时它提供 一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;
为了防止 在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个 Singleton类型的静态对象,作为外部共享的唯一实例。
3、单例模式的使用步骤
(1)构造函数私有化。
(2)提供一个全局的静态方法(全局访问点)来获取单例对象。
(3)在类中定义一个静态指针,指向本类的变量的静态变量指针 。
4、单例模式的优缺点
优点:
(1) 单例模式提供了对唯一实例的受控访问。
(2) 节约系统资源。由于在系统内存中只存在一个对象。
缺点:
(1) 扩展略难。单例模式中没有抽象层。
(2) 单例类的职责过重。
5、适用场景
(1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器 或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。
(2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问 点,不能通过其他途径访问该实例。
6、代码实例
提供了两个释放单例的方式:
//#define UseManual
为自动释放
#define UseManual
手动释放
完整代码:
#include <iostream>
#include<vector>
#include<mutex>
using namespace std;
//懒汉式单例
class CSingleton
{
//#define UseManual
public:
//提供实例对象的唯一接口
static CSingleton* GetInstance()
{
if(m_pInstance == nullptr)
{
mux.lock(); // 双重锁检查
if(m_pInstance == nullptr)
{
m_pInstance = new CSingleton();
}
mux.unlock();
}
m_count ++; //被使用的次数
return m_pInstance;
}
#ifdef UseManual
static void destroyInstance() //当程序结束时候手动调用
{
if(m_pInstance != nullptr)
{
delete m_pInstance ;
}
m_pInstance = nullptr;
}
#endif
void disPlay()
{
cout<<"m_count = "<<m_count<<endl <<"&this =" <<this<<endl;
}
private:
//构造函数私有化
CSingleton(){
cout<<"CSingleton"<<endl;
};
~CSingleton(){
cout<<"~CSingleton"<<endl;
};
//私有化将被唯一实例化的对象
static CSingleton* m_pInstance;
//实例化计数器
static int m_count;
//多线程的互斥锁
static mutex mux;
#ifndef UseManual
class CGarbo //它的唯一工作就是在析构函数中删除CSingleton的实例
{
public:
~CGarbo()
{
cout<<" ~CGarbo"<<endl;
if( CSingleton::m_pInstance!=NULL )
{
delete CSingleton::m_pInstance;
CSingleton::m_pInstance = nullptr;
}
}
};
//定义一个静态成员,程序结束时,系统会自动调用它的析构函数
static CGarbo Garbo;
#endif
};
CSingleton* CSingleton:: m_pInstance = NULL;
int CSingleton:: m_count = 0;
mutex CSingleton::mux;
void fun(uint32_t num)
{
CSingleton *tmpSg= CSingleton::GetInstance();
tmpSg->disPlay();
cout <<"threadId = " << this_thread::get_id()<< " num = " << num << endl ;
}
int main()
{
//使用一组线程去实例化CSingleton 对象
vector<thread> vthread;
for(int i = 0 ; i < 10; i++)
{
vthread.push_back(thread(fun,i));
}
for(thread &t:vthread)
{
t.detach();
}
cout<<"应用程序结束"<<endl;
return 0;
}