(1).饿汉模式
#include<iostream>
#include <mutex>
using namespace std;
template <class T>
class EagerSingleton
{
public :
static T * GetInstance()
{
assert(_instance);
return _instance;
}
//实例销毁(1)一般情况下,不必在乎,因为全局就这一个变量,全局都要用,
//不知道什么时候销毁比较合适,一般他的生命周期就是软件的生命周期,
//软件结束,他就结束了(程序结束时会自动释放它占用的内存资源)
//(2)当在类中打开了文件句柄,数据库连接等,需要手动释放时,就得显示销毁这个实例
static void DelInstance()
{
if (_instance)
{
delete _instance;
_instance = NULL ;
}
}
//RAII 自动回收实例对象
class GC
{
public :
~GC()
{
DelInstance();
}
};
protected :
EagerSingleton();
EagerSingleton( const EagerSingleton & s);
EagerSingleton & operator = (const EagerSingleton& s);
protected :
static T * _instance;
};
template <class T>
T * EagerSingleton <T>::_instance = new T ;
(2).懒汉模式
template <class T>
class LazySingleton
{
public :
T * GetInstance()
{
// 使用双重检查,提高效率,避免高并发场景下每次获取实例对象都进行加锁
if (_instance == NULL )
{
mtx.lock();
if (_instance == NULL )
{
//下面的tmp = new LazyEagerSingleton();编译器可能会进行优化
//上面的代码分为三个部分:1.分配空间 2.调用构造函数 3. 赋值
//编译器优化可能导致2,3重排。这样可能导致高并发场景下,
//其他线程获取到未调用构造函数初始化的对象。解决:加入内存栅栏
//就相当于,当程序中已存在一个未调用构造函数初始化的对象,时间片到了,
//其他线程以为对象已创建好就直接用了,对吧
T * tmp = new T;
MemoryBarrier();
_instance = tmp;
}
mtx.unlock();
}
return _instance;
}
protected :
//构造函数定义为私有,限制只能在类内创建对象
LazySingleton();
LazySingleton( const LazySingleton & s);
LazySingleton & operator=(const LazySingleton& s);
protected :
//1.静态成员无须创建任何对象实例就可以访问。
//2.静态对象在main函数之前初始化,这时只有主线程运行,所以是线程安全的。
static T * _instance;
static mutex mtx;
};
template <class T>
T * LazySingleton <T>::_instance = NULL ;
参考文件:http://blog.csdn.net/lovelion/article/details/8229621
原文地址:http://blog.51cto.com/10707460/2094775