当前位置: 首页 > article >正文

4个线程安全的单例模式

1、概述

单例模式是程序生命周期内,该类只有一个实例,并提供一个该实例访问点,适用于全局配置类、资源管理类等场景。

单实例模式特点:

1、构造函数私有

2、拷贝构造和赋值构造函数为私有

3、类有一个静态方法获取实例

2、静态局部变量(使用最广泛)

C++11标准中,要求局部静态变量初始化具有线程安全性
特性:如果变量在初始化时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束

class Singleton
{
public:
    static Singleton& GetInstance() {
        static Singleton instance;
        return instance;
    }
private:
    Singleton(){}
    ~Singleton();
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
};

3、std::call_once方案

std::call_once是C++11引入的新特性,需要包含头文件<mutex>,确保函数在多线程环境下,只执行一次。

class Singleton {
public:
    ~Singleton()
    {
        instance.reset();
    }

    static Singleton* getInstance() {
        std::call_once(single_flag, []() {
            instance.reset(new Singleton());
        });

        return instance.get();
    }

    Singleton(const Singleton&) = delete;
    void operator=(const Singleton&) = delete;

private:
    Singleton() {};
    static std::once_flag single_flag;
    static std::unique_ptr<Singleton> instance;
};

std::once_flag Singleton::single_flag;
std::unique_ptr<Singleton> Singleton::instance;

4、双检索方案(用的少)

// 加锁的懒汉式实现
class Singleton
{
public:
    // 获取单实例对象
    static Singleton *GetInstance();

    //释放单实例,进程退出时调用
    static void deleteInstance();

    // 打印实例地址
    void Print();

private:
    // 将其构造和析构成为私有的, 禁止外部构造和析构
    Singleton();
    ~Singleton();

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    Singleton(const Singleton &signal);
    const Singleton &operator=(const Singleton &signal);

private:
    // 唯一单实例对象指针
    static Singleton *m_SingleInstance;
    static std::mutex m_Mutex;
};

//初始化静态成员变量
Singleton *Singleton::m_SingleInstance = nullptr;
std::mutex Singleton::m_Mutex;

Singleton * Singleton::GetInstance()
{
    //  这里使用了两个 if 判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,
    //  避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。
    if (m_SingleInstance == nullptr)
    {
        std::unique_lock<std::mutex> lock(m_Mutex); // 加锁
        if (m_SingleInstance == nullptr)
        {
            volatile auto temp = new (std::nothrow) Singleton();
            m_SingleInstance = temp;
        }
    }

    return m_SingleInstance;
}

void Singleton::deleteInstance()
{
    std::unique_lock<std::mutex> lock(m_Mutex); // 加锁
    if (m_SingleInstance)
    {
        delete m_SingleInstance;
        m_SingleInstance = nullptr;
    }
}

void Singleton::Print()
{
    std::cout << "我的实例内存地址是:" << this << std::endl;
}

Singleton::Singleton()
{
    std::cout << "构造函数" << std::endl;
}

Singleton::~Singleton()
{
    std::cout << "析构函数" << std::endl;
}

5、饿汉模式

该模式程序启动时,就将类实例化了。
这种模式有个注意事项:如果业务中有多个饿汉类,要考虑全局初始化顺序和依赖关系。

class Singleton {
private:
    static Singleton* instance; // 单例对象指针
    Singleton() {} // 私有构造函数

public:
    static Singleton* GetInstance() {
        return instance; // 提供一个方法获取单例对象
    }
};

// 在类外初始化静态成员
Singleton* Singleton::instance = new Singleton();

学习链接:https://github.com/0voice


http://www.kler.cn/a/454781.html

相关文章:

  • 数据结构(Java)——链表
  • 【火猫DOTA2】VP一号位透露队伍不会保留原阵容
  • HarmonyOS NEXT 实战之元服务:静态案例效果---查看国内航班服务
  • 2024国赛A问题5
  • Jmeter下载安装配置教程(多版本)
  • 深度学习在自动驾驶车辆车道检测中的应用
  • Python的随机数
  • 关于机器学习当中的决策树算法解析
  • 每日算法一练:剑指offer——动态规划(1)
  • 41.欠采样技术下变频不能用与跨两个nyquist的情况下
  • 探索 DC-SDK:强大的 3D 地图开发框架
  • 第1章 R语言中的并行处理入门
  • C语言技巧之有条件的累加
  • bash shell脚本while循环
  • leetcode 3159. 查询数组中元素的出现位置 中等
  • RDFS—RDF模型属性扩展解析
  • 分布式事务入门 一
  • 一种寻路的应用
  • 期权懂|期权入门知识:如何选择期权合约?
  • 1.1、Python3基础语法
  • GitLab的安装与卸载
  • 解决 vue3 中 echarts图表在el-dialog中显示问题
  • leetcode hot100 腐烂的橘子
  • zabbix5.0版本(安装部署+添加服务器+拆分数据库)
  • 产品初探Devops!以及AI如何赋能Devops?
  • 3-Linux 用户管理入门