懒汉模式线程不安全的解决方法

  • 懒汉模式存在线程不安全,解决方法是:加互斥锁
#include<iostream>
#include<thread>//C++11的线程库
#include<mutex>//互斥锁
using namespace std;
std::mutex mtx;//全局的互斥锁

class Object
{
private:
    int value;
    static Object* pobj;
private:
    Object(int x = 0) :value(x) { cout << "create object" << endl; }//让其在外部不能创建对象
public:
    Object(const Object&) = delete;//删除拷贝构造,防止对象通过拷贝构造创建对象
    Object& operator=(const Object&) = delete;//删除赋值,防止简单类型通过赋值创建对象
public:
    ~Object() { cout << "destroy object" << endl; }//防止某些情况不能正常释放
    //void SetValue(Object* const this,int x=0)
    void SetValue(int x = 0) { value = x; }
    //int GetValue(const Object* const this)
    int GetValue() const { return value; }
    static Object& GetRefObject()//获取实例的静态方法
    {
        mtx.lock();//创建对象前加锁,保证只有一个线程进行创建对象且仅创建一次
        if (nullptr == pobj)//线程判断是否已经创建过对象,如果已经创建则不再创建
        {
            pobj = new Object(10);
        }
        mtx.unlock();//创建完成时解锁
        return *pobj;
    }
};
Object* Object::pobj = nullptr;

void funa()
{
    Object& obja = Object::GetRefObject();
    obja.SetValue(100);
    cout << "&obja  " << &obja << endl;
}

void funb()
{
    Object& objb = Object::GetRefObject();
    cout << objb.GetValue() << endl;
    cout << "&objb  " << &objb << endl;
}

int main()
{
    std::thread tha(funa);
    std::thread thb(funb);
    tha.join();//等待线程结束
    thb.join();//等待线程结束
}

加锁后保证了线程安全,对象仅被创建了一次(obja和objb是同一个地址,Object构造函数只调用一次),线程funa设置的value值未被覆盖。运行结果如下

 

  •  懒汉模式更安全的解决方法是双重锁机制(加锁和if双重判断)

原因:

第一层的if:new出第一个实例后,后面每个线程访问到最外面的if判断,如果已经创建过对象就直接返回了,没有加锁的开销

第二层If,:判断类对象指针为空,才进行实例

[锁机制]:保证同一时刻只有一个线程访问(即进行实例化)

 

#include<iostream>
#include<thread>//C++11的线程库
#include<mutex>//互斥锁
using namespace std;
std::mutex mtx;//全局的互斥锁

class Object
{
private:
    int value;
    static Object* pobj;
private:
    Object(int x = 0) :value(x) { cout << "create object" << endl; }//让其在外部不能创建对象

public:
    Object(const Object&) = delete;//删除拷贝构造,防止对象通过拷贝构造创建对象
    Object& operator=(const Object&) = delete;//删除赋值,防止简单类型通过赋值创建对象
public:
    ~Object() { cout << "destroy object" << endl; }//防止某些情况不能正常释放
    //void SetValue(Object* const this,int x=0)
    void SetValue(int x = 0) { value = x; }
    //int GetValue(const Object* const this)
    int GetValue() const { return value; }
    static Object& GetRefObject()//获取实例的静态方法
    {
        if (nullptr == pobj)//先进行判断,如果pobj不为空(即已经创建过对象),则线程直接跳过这一块域,减少加锁开销
        {
            mtx.lock();//创建前加锁,防止其他线程进行二次创建
            if (nullptr == pobj)//线程判断是否已经创建过对象,保证单例模式创建对象唯一性
            {
                pobj = new Object(10);
            }
            mtx.unlock();//创建完成时解锁
        }
        return *pobj;
    }
};
Object* Object::pobj = nullptr;

void funa()
{
    Object& obja = Object::GetRefObject();
    obja.SetValue(100);
    cout << "&obja  " << &obja << endl;
}

void funb()
{
    Object& objb = Object::GetRefObject();
    cout << objb.GetValue() << endl;
    cout << "&objb  " << &objb << endl;
}

int main()
{
    std::thread tha(funa);
    std::thread thb(funb);
    tha.join();//等待线程结束
    thb.join();//等待线程结束
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宠宠熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值