单例类设计模式、call_once

单例类设计模式

软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

 而单例类设计模式就是一种常用的软件设计模式。这种设计模式确保类仅生成一个对象。并提供一个全局的访问点来访问该对象。常用于配置文件的读取、数据库连接池、线程池等场景。

在单例类设计模式中,类的构造函数通常是private的,并提供一个静态的函数返回该类的唯一实例对象。当第一次调用该该静态函数时,就会创建该类的唯一实例对象,当此后再调用该静态函数时,则返回已经创建的实例对象,不再创建新的实例对象。

#include<iostream>
#include<thread>
#include<mutex>

using namespace std;

mutex mymutex;//全局互斥量

class Singleton
{
public:
    static Singleton* getInstance()
    {
        if (instance==NULL) //双重判断,提高效率
        {
            unique_lock<std::mutex>  myunmutex(mymutex);//防止多线程同时执行导致出现多个实例对象
            if (instance == NULL)
            {
                instance = new Singleton();
                static CGarclear c1;
            }
         }
        return instance;
    }

    class CGarclear//利用其析构释放new的Singleton对象内存
    {
    public:
        ~CGarclear()
        {
            if (Singleton::instance)
            {
                delete Singleton::instance;
                Singleton::instance = NULL;
            }
        }
    };

private:
    static Singleton* instance;
    Singleton() {}//私有构造函数
   
};
 
Singleton* Singleton::instance =NULL;//初始化静态成员

void mythread()//线程入口函数
{
    Singleton* p =Singleton::getInstance();
}
int main()
{
    thread mytobj1(mythread);
    thread mytobj2(mythread);
    mytobj1.join();
    mytobj2.join();

}

使用单例类设计模式时,最后在主线程main函数中线程执行前实例单例类对象。否则就有可能造成多个线程一起执行getInstance()函数,当某一线程判断instance为空但还未new时,跳转到另一线程同样判断instance为空,这样执行多次new造成出现多个实例对象。因此如果有在自主线程执行后使用单例类的需求,就应该使用互斥量防止以上情况的发生。同时为了避免多次使用互斥量导致代码效率下降,可以使用双重判断,确保仅在instance为空时才调用互斥量。

call_once

std::call_once 是 C++11 引入的一个函数,用于确保某个操作只执行一次,即使在多线程环境中被多次调用。因此call_once对于单例类的实现十分有用。

std::call_once需要一个 std::once_flag(实际上是一个结构) 对象作为参数,该对象用于跟踪函数是否已经执行过。当 std::call_once 被调用时,它会检查 std::once_flag 的状态。如果函数尚未执行,std::call_once就会执行提供的可调用对象(通常是一个函数或 lambda 表达式),并将 std::once_flag设置为已执行状态。如果函数已经执行过,std::call_once`则不会再次执行它。

 使用call_once 改造上面代码:

#include<iostream>
#include<thread>
#include<mutex>

using namespace std;

mutex mymutex;//全局互斥量
once_flag g_flag;

class Singleton
{
private:
    static void createInstance()
    {
        instance = new Singleton();
        static CGarclear cl;
    }
public:
    static Singleton* getInstance()
    {
        call_once(g_flag,createInstance );//确保仅执行一次createInstance
        return instance;
    }

    class CGarclear//利用其析构释放new的Singleton对象内存
    {
    public:
        ~CGarclear()
        {
            if (Singleton::instance)
            {
                delete Singleton::instance;
                Singleton::instance = NULL;
            }
        }
    };

private:
    static Singleton* instance;
    Singleton() {}//私有构造函数

};

Singleton* Singleton::instance = NULL;//初始化静态成员

void mythread()//线程入口函数
{
    Singleton* p = Singleton::getInstance();
}
int main()
{
    thread mytobj1(mythread);
    thread mytobj2(mythread);
    mytobj1.join();
    mytobj2.join();

}

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鬼多不菜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值