单例模式的概念
只允许一个产生一个对象的类单例模式的实现方法
1.单例类保证全局只有唯一一个自行创建的实例对象2.单例类提供获取这个唯一实例的接口
单例模式的优缺点
优点
(1)阻止其他度对象实例化自己的副本,保证所有访问唯一性(2)类控制了实例化的过程,所以可以灵活的更改实例化的过程
缺点
(1)每次都需要检查是否对象已经生成,造成些微的开销(2)使用单例对象时,开发人员可能会意外发现自己无法实例化该类
单例模式的分类
懒汉模式(适用于各种场景)
在需要的时候创建对象懒汉模式需要加入synchronized才可以保证线程安全
饿汉模式(在某些场景下受到限制)
在main函数开始的时候即创建对象饿汉模式是线程安全的
代码实现
懒汉模式的实现
普通版本
class SingleTon
{
public:
static SingleTon* GetInstance()//获取对象实例的唯一接口
{
if (_inst == NULL)
{
_inst = new SingleTon;
}
return _inst;
}
void Print()
{
cout << "SingleTon : " << _a << endl;
}
private:
SingleTon()//防止构造函数创建对象
:_a(0)
{}
SingleTon& operator=(const SingleTon&) = delete;
SingleTon(const SingleTon&) = delete;
int _a;
static SingleTon* _inst;//指向实例化的指针定义成静态成员
};
SingleTon* SingleTon::_inst = NULL;
线程安全版本
加入RAII机制,避免死锁的出现
class SingleTon
{
public:
static SingleTon* GetInstance()//获取对象实例的唯一接口
{
if (NULL == _inst)//只有在创建实例的时候才进行加锁提高效率
{
lock_guard<mutex>lock(_mtx);
if (_inst == NULL)
{
_inst = new SingleTon;
}
}
return _inst;
}
void Print()
{
cout << "SingleTon : " << _a << endl;
}
private:
SingleTon()//防止构造函数创建对象
:_a(0)
{}
SingleTon& operator=(const SingleTon&) = delete;
SingleTon(const SingleTon&) = delete;
int _a;
static SingleTon* _inst;//指向实例化的指针定义成静态成员
static mutex _mtx;//保证安全的互斥锁
};
SingleTon* SingleTon::_inst = NULL;
mutex SingleTon::_mtx;
内存栅栏技术&单例对象的释放
添加双检查机制来提高效率
添加内存栅栏技术来防止由于提升效率而打乱执行的顺序
对单例模式的释放,下面这种方法是有问题的
最好是调用atexit回调机制,在main函数结束完毕后再进行释放
class SingleTon
{
public:
static SingleTon* GetInstance()//获取对象实例的唯一接口
{
if (NULL == _inst)//只有在创建实例的时候才进行加锁提高效率
{
lock_guard<mutex>lock(_mtx);
if (_inst == NULL)
{
SingleTon* tmp = new SingleTon;
MemoryBarrier();//内存栅栏技术
_inst = tmp;
}
}
return _inst;
}
void Print()
{
cout << "SingleTon : " << _inst << endl;
}
static void DellInstance()
{
lock_guard<mutex>lock(_mtx);
if (_inst)
{
cout << "delete " << endl;
delete _inst;
_inst = NULL;
}
}
private:
SingleTon()//防止构造函数创建对象
:_a(0)
{}
SingleTon& operator=(const SingleTon&) = delete;
SingleTon(const SingleTon&) = delete;
int _a;
static SingleTon* _inst;//指向实例化的指针定义成静态成员
static mutex _mtx;//保证安全的互斥锁
};
SingleTon* SingleTon::_inst = NULL;
mutex SingleTon::_mtx;
饿汉模式的实现
简洁,高效,不用加锁
但是在特定情况下会出现问题
实现方法1
class Singleton
{
public:
static Singleton& GetInstance()
{
assert(_inst);
return *_inst;
}
void Print()
{
cout << "Singleton : " << _inst << endl;
}
private:
Singleton()
:_a(0)
{}
int _a;
Singleton& operator=(const Singleton&) = delete;
Singleton(const Singleton&) = delete;
static Singleton* _inst;
};
Singleton* Singleton::_inst = new Singleton;
实现方法2
class Singleton
{
public:
static Singleton& GetInstance()
{
static Single _inst;
return *_inst;
}
void Print()
{
cout << "Singleton : " << _inst << endl;
}
private:
Singleton()
:_a(0)
{}
int _a;
Singleton& operator=(const Singleton&) = delete;
Singleton(const Singleton&) = delete;
static Singleton* _inst;
};
Singleton* Singleton::_inst = NULL;