单例模式等

3 篇文章 0 订阅

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() 方法会返回一个未定义的实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值