并发编程7——单例模式、call_once

目录

一、单例设计模式

  •   &m_instance 0x00007ff79f52f340 {Cpp.exe!MyCAS  *MyCAS::m_instance} {0x000001a2aee80850 {...}}   MyCAS * *
    
  •   &MyCAS::m_instance  0x00007ff79f52f340 {Cpp.exe!MyCAS  *MyCAS::m_instance} {0x0000000000008123 {...}}   MyCAS * *
    

单例设计模式中,不能通过类名 对象的方式创建对象了,只能通过调用类的静态成员函数来创建对象。

二、单例设计模式共享数据问题分析、解决

面临的问题——本来是在主线程中创建对象,并将需要装载的数据装载好。

但是如果需要在自己创建的线程中创建MyCAS这个单例类的对象,这种线程可能不止2个(最少2个),那么我们需要面临GetInstance()这种成员函数要互斥。

  • 使用了双重锁定

三、std::call_once()

这个是C++11引入的函数,这个函数的第二个参数会是一个函数名go()call_once()的功能是就算有10个线程要调用go()这个函数,但是go()这个函数只会被调用一次。

  • call_once具备互斥量这种能力,并且效率高,比互斥量消耗的资源更少
  • call_once需要与一个标记结合使用,std::once_flag,这个once_flag其实是一个结构
  • call_once本质上就是通过这个标记来决定对应的函数go()是否执行,调用call_once()成功后,call_once就会把flag这个标记设置为一种已调用的状态,后面再调用call_once(),只要flag被设置为了已调用的状态,那么对应的函数go()就不会再被执行了。

博客示例源代码

  • 主线程创建对象
#include 

using namespace std;


class MyCAS
{
private:
    MyCAS() {}

private:
    static MyCAS* m_instance;

public:
    static MyCAS* GetInstance()
    {
        if (m_instance == NULL)
        {
            m_instance = new MyCAS();
            static CGarhuishou cl;
        }
        return m_instance;
    }

    // 类中套类,用来释放对象
    class CGarhuishou
    {
    public:
        ~CGarhuishou()
        {
            if (MyCAS::m_instance)
            {
                delete MyCAS::m_instance;
                MyCAS::m_instance = NULL;
            }
        }
    };

    void func() { cout << "测试" << endl; }
};


MyCAS* MyCAS::m_instance = NULL;

int main()
{
    MyCAS* p_a = MyCAS::GetInstance();  // 创建一个对象,返回该类(MyCAS)对象的指针

    p_a->func();
    MyCAS::GetInstance()->func();

    return 0;
}
  • 双重锁
#include 
#include 
#include 

using namespace std;

// 定义一个互斥量
std::mutex resource_mutex;
std::once_flag g_flag;

class MyCAS
{
private:
    MyCAS() {}

private:
    static MyCAS* m_instance;

public:
    static MyCAS* GetInstance()
    {
        // 外面的if判断是提高效率
        // a) 如果 if (m_instance != NULL) 条件成立,一定表示m_instance已经被new过了
        // b) 如果 if (m_instance == NULL) 条件成立,不代表m_instance一定没被new过

        if (m_instance == NULL) // 双重锁定(双重检查)用来提高效率
        {
            std::unique_lock mymutex(resource_mutex); // 自动加锁
            if (m_instance == NULL)
            {
                m_instance = new MyCAS();  // 共享数据
                static CGarhuishou cl;
            }
        }

        return m_instance;
    }

    // 类中套类,用来释放对象
    class CGarhuishou
    {
    public:
        ~CGarhuishou()
        {
            if (MyCAS::m_instance)
            {
                delete MyCAS::m_instance;
                MyCAS::m_instance = NULL;
            }
        }
    };

    void func() { cout << "测试" << endl; }
};


MyCAS* MyCAS::m_instance = NULL;

// 线程入口函数
void mythread()
{
    cout << "我的线程开始执行了" << endl;
    MyCAS* p_a = MyCAS::GetInstance();
    cout << "我的线程执行完毕了" << endl;

    return;
}

int main()
{
    std::thread mytobj1(mythread);
    std::thread mytobj2(mythread);

    mytobj1.join();
    mytobj2.join();

    return 0;
}
  • call_once
#include 
#include 
#include 

using namespace std;

// 定义一个互斥量
std::mutex resource_mutex;
std::once_flag g_flag;

class MyCAS
{

    static void CreateInstance()
    {
        std::chrono::milliseconds dura(20000);
        std::this_thread::sleep_for(dura);

        cout << "CreateInstance()被执行了" << endl;

        m_instance = new MyCAS();
        static CGarhuishou cl;
    }

private:
    MyCAS() {}

private:
    static MyCAS* m_instance;

public:
    static MyCAS* GetInstance()
    {
        // 外面的if判断是提高效率
        // a) 如果 if (m_instance != NULL) 条件成立,一定表示m_instance已经被new过了
        // b) 如果 if (m_instance == NULL) 条件成立,不代表m_instance一定没被new过


        std::call_once(g_flag, CreateInstance); // g_flag相当于一个锁(互斥量)
                                                // 通过g_flag这个标记,保证CreateInstance只被调用一次
        cout << "call_once()执行完毕" << endl;
        return m_instance;
    }

    // 类中套类,用来释放对象
    class CGarhuishou
    {
    public:
        ~CGarhuishou()
        {
            if (MyCAS::m_instance)
            {
                delete MyCAS::m_instance;
                MyCAS::m_instance = NULL;
            }
        }
    };

    void func() { cout << "测试" << endl; }
};


MyCAS* MyCAS::m_instance = NULL;

// 线程入口函数
void mythread()
{
    cout << "我的线程开始执行了" << endl;

    MyCAS* p_a = MyCAS::GetInstance();
    p_a->func();

    cout << "我的线程执行完毕了" << endl;

    return;
}

int main()
{
    std::thread mytobj1(mythread);
    std::thread mytobj2(mythread);

    mytobj1.join();
    mytobj2.join();

    return 0;
}

你可能感兴趣的:(并发编程7——单例模式、call_once)