线程安全的单例模式:
单例模式:属于创建类型的一种常用的软件设计模式,通过单例模式创建的类在当前进程中只有一个实例,一份资源只能被申请加载一次。
如何实现:
-
饿汉模式:资源在程序初始化的时候就去加载,后边使用的时候直接使用,使用会非常流畅,但是有可能会加载上根本用不到的资源,而且程序初始化的时间也会较慢
-
懒汉模式:在进行资源的使用时,缺少这个资源才去加载,程序初始化的速度比较快,但是初次加载某个模块时会比较慢,因为这时候需要加载相应的资源。
饿汉模式实现方式:
使用static将某成员变量定义为静态成员变量,这样所有对象共用同一份资源,并且在程序初始化的时候就会加载资源,不涉及线程安全
代码:
class single_instance{
public:
int* get_instance()
{
return &_data;
}
private:
static int _data;
};
int single_instance::_data=10;
int main()
{
single_instance a;
single_instance b;
printf("a:%d-----%p\n",*(a.get_instance()),a.get_instance());
printf("b:%d-----%p\n",*(b.get_instance()),b.get_instance());
return 0;
}
运行结果:
可以看到a和b两个对象使用的都是同一个数据资源
懒汉模式实现方式:
- 使用static保证所有对象使用同一份资源
- 使用volatile防止编译器过度优化
- 实现线程安全,保证资源判断及申请过程都是安全的
- 外部进行二次判断,避免资源已经加载成功多次获取锁资源,以及所带来的锁冲突
代码:
pthread_mutex_t mutex;
class single_instance{
public:
volatile int* get_instance()
{
if(_data==NULL)
{
pthread_mutex_lock(&mutex);
if(_data==NULL)
{
_data=new int;
*_data=10;
}
pthread_mutex_unlock(&mutex);
}
return _data;
}
private:
volatile static int *_data;
};
volatile int* single_instance:: _data=NULL;
int main()
{
pthread_mutex_init(&mutex,NULL);
single_instance a;
single_instance b;
printf("a:%d-%p\n", *(a.get_instance()), a.get_instance());
printf("b:%d-%p\n", *(b.get_instance()), b.get_instance());
pthread_mutex_destroy(&mutex);
return 0;
}
运行结果:
对象a在需要使用数据时,加载了数据,b对象在使用时直接使用