以前面试的时候经常被问到singleton, 以前不明觉厉, 觉得不太理解singleton 的重要性。工作中,却发现singleton这个设计模式,在工程中广泛应用。
下面给出两种singleton 模式
一、懒汉模式:即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例。
需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety.
使用double-check来保证thread safety但是如果处理大量数据时,该锁才成为严重的性能瓶颈。
1、静态成员实例的懒汉模式:
class Singleton
{
private:
static Singleton* m_instance;
Singleton(){}
public:
static Singleton* getInstance();
};
Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
二、饿汉模式:即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在以后仅返回此实例。
由静态初始化实例保证其线程安全性,WHY?因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。
故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。
class SingletonStatic
{
private:
static const SingletonStatic* m_instance;
SingletonStatic(){}
public:
static const SingletonStatic* getInstance()
{
return m_instance;
}
};
//外部初始化 before invoke main
const SingletonStatic* SingletonStatic::m_instance = new SingletonStatic();
下面给出一个完整的double check 方法的线程安全的singleton模版类
template<typename T>
class Singleton(){
NOCOPY_CLASS(singleton);
public:
static T& GetInstance() {
if(instance_ == NULL) {
lock_.Lock();
if(instance_ == NULL) {
intstance_ = new T;
}
lock_.Unlock();
}
return *instance_;
}
protected:
Singleton();
~Singleton();
private:
static T* volatile instance_;
static MutexLock lock_;
};
template<typename T>
T * volatile Singleton<T>::instance_ = NULL;
template<typename T>
MutexLock Singleton<T>::lock_;