c++单列模式与线程安全
2014-07-27 12:04
489 查看
通常c++里面的单列模式很容易实现,我们也不需要去考虑其线程安全的问题,但是在多线程环境中我们却必须要考虑到。首先我们来分析下一下的这个单列模式为什么不是线程安全的,通常的单列模式写法:
class MsgOfArrival { public: ~MsgOfArrival(void); MAP_STRING_PNORMALMSGCOLLECTION m_normalmsgMap; static MsgOfArrival* GetInstance(); private: MsgOfArrival(void); static MsgOfArrival* m_pInstance; }; MsgOfArrival* MsgOfArrival::m_pInstance = NULL; MsgOfArrival::MsgOfArrival(void) { } MsgOfArrival::~MsgOfArrival(void) { }
假设两个多线程同时执行GetInstance()函数,那么m_pInstance==NULL时, 两个线程同时进入了if中时就会创建两个指针,这当然是不行的。解决这个问题首先我们会想到加锁,如改成
MsgOfArrival* MsgOfArrival::GetInstance() { if (m_pInstance == NULL) { EnterCriticalSection(&g_cs); m_pInstance = new MsgOfArrival; LeaveCriticalSection(&g_cs)
} return m_pInstance;
}这样当然可以,而且m_pInstance一但new成功,GetInstance调用不会在进入if中,所以大量调用该单列并不会因为临界区造成性能瓶颈。 第二种方法是静态变量初始化的时候,我们直接让其new一个指针,因为我们知道静态变量是在Main函数还没执行的时候就由主线程完成了初始化,既然单例指针还没进入到main就已经构造了, 那么我们当然不需要在进入main以后的多线程中来担心单例构造的线程安全性。代码如下:
class MsgOfArrival需要注意m_pInstance使用const进行修饰的,其所指对象是const的也就是说我们不能修改这个单列对象,这也要求我们在调用改单列的函数时该函数也必须是const的如:
{
public:
~MsgOfArrival(void);
MAP_STRING_PNORMALMSGCOLLECTION m_normalmsgMap;
static const MsgOfArrival* GetInstance();
private:
MsgOfArrival(void);
static const MsgOfArrival* m_pInstance;
};const MsgOfArrival* MsgOfArrival::m_pInstance = new MsgOfArrival;
MsgOfArrival::MsgOfArrival(void)
{
}MsgOfArrival::~MsgOfArrival(void)
{
}const MsgOfArrival* MsgOfArrival::GetInstance()
{
return m_pInstance;
}
int getdata() const; //函数声明//函数定义当然m_pInstance也可以不用const修饰, 但是这样其其内部数据可以被修改, 这样在多线程的时候是很危险的。 上面单例模式已经是线程安全的, 但是有个问题, 这个单例被创建后如何释放呢?第一种方法 在在类里面增加一个静态的函数用于释放指针,这样做在程序中我们随时可以释放单例指针。但是有时候我们的单例指针要一直伴随着进程结束,这个时候我们就可以采用第二种方法:
int MsgOfArrival::getdata() const
{
//
// return m_nVal;
}
class MsgOfArrival我们在类里面添加了一个CGarbo类,这个类只有一个作用负责清除单列对象指针,定义一个static的Garbo对象, 该对象声明周期与单例对象指针是一样的,这个静态Garbo对象也会在程序结束时释放,这个时候会将单例指针所拥有资源也释放掉。注意SAFE_DELETE是我自己定义的释放宏。 文章若有不妥,请大家指教。
{
public:
~MsgOfArrival(void);
MAP_STRING_PNORMALMSGCOLLECTION m_normalmsgMap;
static const MsgOfArrival* GetInstance();
private:
class CGarbo
{
public:
~CGarbo()
{
SAFE_DELETE(MsgOfArrival::m_pInstance);
}
};
static CGarbo Garbo; //清理资源
MsgOfArrival(void);
static const MsgOfArrival* m_pInstance;
};//注意静态对象也必须想变量一样初始化,否则这个静态对象不存在,也就不会去执行析构函数
MsgOfArrival::CGarbo MsgOfArrival:: Garbo; //清理资源
相关文章推荐
- C++单列模式的实现
- 单例模式——C++(线程安全)
- C++线程安全的单例模式
- 单例模式——C++实现线程安全的单例
- 多线程下线程安全的单列模式
- C++ 线程安全的单例模式
- C++ 线程安全的单例模式
- C++ 线程安全的单例模式
- C++ 线程安全的单例模式
- 单例模式——C++实现线程安全的单例
- 线程安全的单列模式
- 单例模式——C++实现线程安全的单例
- C++ 线程安全的单例模式
- C++实现线程安全的单例模式
- 单例模式——C++实现线程安全的单例
- C++ 线程安全的 单实例 模式
- C++ 线程安全的单例模式
- C++ 线程安全的单例模式
- 单例模式——C++实现线程安全的单例 .
- 单例模式——C++实现线程安全的单例