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

  • 懒汉模式存在线程不安全,解决方法是:加互斥锁
#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();//等待线程结束
}

猜你喜欢

转载自blog.csdn.net/weixin_53472334/article/details/131989259
今日推荐