4个线程安全的单例模式

ops/2024/12/31 22:40:55/

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.ppmy.cn/ops/145943.html

相关文章

C#-调用C++接口

一.静态&动态装载DLL C中接口通过编译为DLL对外提供调用,C#需要将DLL加载至本应用才可实现C接口调用. 1.静态装载 C#应用程序在编译为可执行exe时将外部DLL装载至本应用中,例如在CSC编译指令中添加相关参数可实现DLL引用. csc /reference:user32.dll /out:HelloWorld.exe 2…

简单园区网拓扑实验

1.实验拓扑 2.实验要求 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及主网关 SW2为vlan 20/30的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan 4、上层通过静态路由协议完成数据通信过程 5、AR1为企业出口路由器 6、要求全网可…

2025最新版Java面试八股文大全

一、Java并发面试题 1、 ThreadLocal 1.1 谈谈你对ThreadLocal的理解&#xff1f; ThreadLocal的作用主要是做数据隔离&#xff0c;填充的数据只属于当前线程&#xff0c;变量的数据对别的线程而言是相对隔离的。它不是针对程序的全局变量&#xff0c;只是针对当前线程的全局…

MySQL中Performance Schema库的详解(上)

使用Performance Schema 将通过一些示例来演示如何使用Performance Schema解决常见的故障案例。 检查SQL语句 要启用语句检测&#xff0c;需要启用statement类型的插桩&#xff0c;如表1所述 ​ 表1&#xff1a;statement类型的插桩及其描述 插装类描述statement/spSQL语句…

渗透测试中常见的端口

端口合计详情 21 ftp22 SSH23 Telnet80 web80-89 web161 SNMP389 LDAP443 SSL心脏滴血以及一些web漏洞测试445 SMB512,513,514 Rexec873 Rsync未授权1025,111 NFS1433 MSSQL1521 Oracle:(iSqlPlus Port:5560,7778)2082/2083 cpanel主机管理系统登陆 &#xff08;国外用较多&am…

Druid连接池管理连接池中的空闲连接驱逐流程

Druid连接池中的驱逐空闲线程流程主要涉及以下几个步骤&#xff1a; 1. 创建和启动驱逐线程 createAndStartDestroyThread 方法&#xff1a;此方法负责创建和启动负责驱逐空闲连接的线程。如果提供了 destroyScheduler&#xff08;一个调度器&#xff09;&#xff0c;则使用该…

info There appears to be trouble with your network connection. Retrying

这个错误信息表明你在使用包管理器安装项目依赖时遇到了网络连接问题。 可能的解决方法&#xff1a; 检查当前node.js版本是否过低。 建议使用当前长期支持版本 yarn的淘宝镜像&#xff1a;yarn的淘宝镜像-CSDN博客 nvm常用命令:NVM常用命令-CSDN博客 下载 | Node.js 中文…

如何在网页端使用 IDE 高效地阅读 GitHub 源码?

如何在网页端使用 IDE 高效地阅读 GitHub 源码&#xff1f; 前言什么是 GitHub1s&#xff1f;使用 GitHub1s 阅读 browser-use 项目源码步骤 1: 打开 GitHub 项目页面步骤 2: 修改 URL 使用 GitHub1s步骤 3: 浏览文件结构步骤 4: 使用代码高亮和智能补全功能步骤 5: 快速跳转和…