线程安全问题通常是由全局以及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
- 单例模式
简单的单例模式在实现上是以下面的方式来实现的,这一种写法是线程安全的:
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <windows.h>
class SingletongClass
{
private: //构造函数私有
SingletongClass()
{
pthread_mutex_init(&mutex);
}
SingletongClass(int m)
{
pthread_mutex_init(&mutex);
}
SingletongClass(const SingletongClass&); //拷贝构造函数不实现,防止拷贝产生多个实例
SingletongClass& operator = (const SingletongClass&); //复制构造函数不实现,防止赋值产生多个实例
public:
static SingletongClass* getInstance() //提供全局访问点
{
pthread_mutex_lock(&mutex);
static SingletongClass m_singleton; //c++11保证了多线程安全,程序退出时,释放资源
pthread_mutex_unlock(&mutex);
return &m_singleton;
}
private:
static pthread_mutex_t mutex;
};
#endif
- 用shared_ptr / weak_ptr管理
- shared_ptr 控制对象的生命期。shared_ptr 是强引用 (想象成用铁丝绑住堆上的对象),只要有一个指向 x 对象的 shared_ptr 存在,该 x 对象就不会析构。 当指向对象 x 的最后一个 shared_ptr 析构或 reset 的时候, x 保证会被销毁。
- weak_ptr 不控制对象的生命期,但是它知道对象是否还活着(想象成用棉线轻轻拴住堆上的对象) 。如果对象还活着,那么它可以提升(promote) 为有效的 shared_ptr; 如果对象已经死了,提升会失败,返回一个空的 shared_ptr。“ 提升”行为是线程安全的。
- shared_ptr/weak_ptr 的“ 计数” 在主流平台上是原子操作,没有用锁,性能不俗。
- shared_ptr 本身不是100% 线程安全的。它的引用计数本身是安全且无锁的,但对象的读写则不是,因为shared_ptr 有两个数据成员,读写操作不能原子化。