https://blog.csdn.net/crayondeng/article/details/24853471?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163163491516780262566416%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163163491516780262566416&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-4-24853471.pc_search_ecpm_flag&utm_term=c%2B%2B%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187
经典线程安全 懒汉
1class single{
2private:
3 //私有静态指针变量指向唯一实例
4 static single *p;
5
6 //静态锁,是由于静态函数只能访问静态成员
7 static pthread_mutex_t lock;
8
9 //私有化构造函数
10 single(){
11 pthread_mutex_init(&lock, NULL);
12 }
13 ~single(){}
14
15public:
16 //公有静态方法获取实例
17 static single* getinstance();
18
19};
20
21pthread_mutex_t single::lock;
22
23single* single::p = NULL;
24single* single::getinstance(){
25 if (NULL == p){
26 pthread_mutex_lock(&lock);
27 if (NULL == p){
28 p = new single;
29 }
30 pthread_mutex_unlock(&lock);
31 }
32 return p;
33}
如果只检测一次,在每次调用获取实例的方法时,都需要加锁,这将严重影响程序性能。双层检测可以有效避免这种情况,仅在第一次创建单例的时候加锁,其他时候都不再符合NULL == p的情况,直接返回已创建好的实例。
前面的双检测锁模式,写起来不太优雅,《Effective C++》(Item 04)中的提出另一种更优雅的单例模式实现,使用函数内的局部静态对象,这种方法不用加锁和解锁操作。
1class single{
2private:
3 single(){}
4 ~single(){}
5
6public:
7 static single* getinstance();
8
9};
10
11single* single::getinstance(){
12 static single obj;
13 return &obj;
14}
C++11以后,要求编译器保证内部静态变量的线程安全性,故C++11之后该实现是线程安全的,C++0x之前仍需加锁,其中C++0x是C++11标准成为正式标准之前的草案临时名字。
饿汉模式
1class single{
2private:
3 static single* p;
4 single(){}
5 ~single(){}
6
7public:
8 static single* getinstance();
9
10};
11single* single::p = new single();
12single* single::getinstance(){
13 return p;
14}
15
16//测试方法
17int main(){
18
19 single *p1 = single::getinstance();
20 single *p2 = single::getinstance();
21
22 if (p1 == p2)
23 cout << "same" << endl;
24
25 system("pause");
26 return 0;
27}
饿汉模式不需要用锁,就可以实现线程安全。原因在于,在程序运行时就定义了对象,并对其初始化。之后,不管哪个线程调用成员函数getinstance(),都只不过是返回一个对象的指针而已。所以是线程安全的,不需要在获取实例的成员函数中加锁。
饿汉模式虽好,但其存在隐藏的问题,在于非静态对象(函数外的static对象)在不同编译单元中的初始化顺序是未定义的。如果在初始化完成之前调用 getInstance() 方法会返回一个未定义的实例。