谈单例模式的线程安全(下)
在这一部分重点讲单例对象如何销毁,及单例类模板,代码中用到的CriticalSection类实现请参考第一部分。
单例对象创建方式可以分两种,一种方法是事先在静态区创建好,即创建成static的,不必考虑delete问题;另一种方法是在堆上创建,在堆上创建就要考虑销毁问题。
单例对象的销毁,可以利用静态对象生命周期来控制,静态数据在程序结束的时候自动销毁,在静态对象的析构函数中delete堆上的内存,看代码:
class SingleQueue
{
public:
static SingleQueue* GetInstance(){
if(!m_){
cs.Lock(); // 注意写法,这里要同步一下
if(!m_){
m_ = new SingleQueue;
}
cs.UnLock();
}
return m_;
}
~SingleQueue(){}
private:
SingleQueue(){}
private:
static SingleQueue* m_; // 在cpp中初始化为NULL
// 仅仅用于SingleQueue单例对象的回收,外界无需使用,为SingleQueue内部类且
// private型即可。
class Garbo
{
public:
~Garbo()
{
if(Singleton<T>::m_){
delete Singleton<T>::m_;
Singleton<T>::m_ = NULL;
}
}
};
static Garbo garbo;
};
在.cpp中:
SingleQueue::Garbo SingleQueue::garbo;
通常工程中用单例模式的类不止一个,为了使这些代码可复用,下面写了个单例类模板:
template <typename T>
class Singleton
{
public:
static T* GetInstance()
{
if(!m_)
{
garbo; // 防止编译器将Garbo优化掉
cs.Lock();
if(!m_)
m_ = new T();
cs.UnLock();
}
return m_;
}
~Singleton(){}
protected:
Singleton(){}
static T* m_;
static CriticalSection cs;
class Garbo
{
public:
~Garbo()
{
if(Singleton<T>::m_){
delete Singleton<T>::m_;
Singleton<T>::m_ = NULL;
}
}
};
static Garbo garbo;
};
template<typename T>
T* Singleton<T>::m_ = NULL;
template<typename T>
CriticalSection Singleton<T>::cs;
template<typename T>
typename Singleton<T>::Garbo Singleton<T>::garbo;
使用的时候直接从Singleton派生就可以,eg:
class CA : public Singleton< CA >
{
public:
friend class Singleton< CA >; // 友元是为了能调用CA的构造
protected:
CA (){}
~ CA (){}
};
这样,CA就是一个单例类,通过CA::GetInstance ()取对象指针。
补充:综合编程 , 安全编程 ,