单例模式-线程安全

在懒汉式下,如果使用多线程,会出现线程安全隐患。为了解决这个问题,可以引入双检锁 - 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 的析构函数,该析构函数会进行资源的释放。
这种方式的最大优点就是在“不知不觉”中进行,所以,对我们来说,尤为省心。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值