在懒汉式下,如果使用多线程,会出现线程安全隐患。为了解决这个问题,可以引入双检锁 - DCL 机制。
#include
#include
using namespace std;
头文件代码:
class BookManager
{
public:
static BookManager * bookmanager(); //静态方法 ,供外界获取它的静态实例。(公有静态函数)
private:
static BookManager *p; //私有静态指针
double Capital; //拥有资金
double Earnings; //收益
BookManager() { Capital = 1000; Earnings = 0; } //让构造函数为 private,这样该类就不会被实例化
static mutex m_mutex; // 锁
}
源文件代码:
BookManager *BookManager::p = NULL; //私有静态指针(静态成员变量必须在类外面初始化)
mutex BookManager::m_mutex; //锁
BookManager * BookManager::bookmanager() //静态方法,供外界获取它的静态实例。
{
if (p == NULL)
{
std::lock_guardstd::mutex lock(m_mutex); // 自解锁
if (p == NULL)
{
p = new BookManager;
}
}
return p;
}
这样,就可以保证线程安全了,但是,会带来较小的性能影响。
资源释放
有内存申请,就要有对应的释放,可以采用下述两种方式:
主动释放(手动调用接口来释放资源)
自动释放(由程序自己释放)
要手动释放资源,添加一个 static 接口,编写需要释放资源的代码:
// 单例 - 主动释放
static void DestoryInstance()
{
if (p != NULL)
{
delete p;
p = NULL;
}
}
然后在需要释放的时候,手动调用该接口:
BookManager::GetInstance()->DestoryInstance();
方式虽然简单,但很多时候,容易忘记调用 DestoryInstance()。这时,可以采用更方便的方式:
头文件代码:
class BookManager
{
public:
static BookManager * bookmanager(); //静态方法 ,供外界获取它的静态实例。(公有静态函数)
static mutex m_mutex; // 锁
private:
static BookManager *p; //私有静态指针(指向单例对象的指针)
double Capital; //拥有资金
double Earnings; //收益
BookManager() { Capital = 1000; Earnings = 0; } //让构造函数为 private,这样该类就不会被实例化
// GC 机制
class GC
{
public:
~GC()
{
// 可以在这里销毁所有的资源,例如:db 连接、文件句柄等
if (p != NULL)
{
cout << "Here destroy the m_pSingleton..." << endl;
delete p;
p = NULL;
}
}
static GC gc; // 用于释放单例
};
};
Main.cpp代码:
只需要声明 BookManager::GC 即可:
#include"BookManager.h"
BookManager::GC BookManager::GC::gc; // 重要
void main()
{
BookManager *p1 = BookManager::bookmanager();
BookManager *p2 = BookManager::bookmanager();
cout << (p1 == p2) << endl;
}
在程序运行结束时,系统会调用 Singleton 的静态成员 GC 的析构函数,该析构函数会进行资源的释放。
这种方式的最大优点就是在“不知不觉”中进行,所以,对我们来说,尤为省心。