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

单例模式-如何保证全局唯一性?

以下是几种实现单例模式并保证全局唯一性的方法:

1. 饿汉式单例模式

class Singleton {
private:// 私有构造函数,防止外部创建对象Singleton() {}// 静态成员变量,存储单例对象static Singleton instance;
public:// 公有静态成员函数,用于获取单例对象static Singleton& getInstance() {return instance;}
};// 静态成员变量的初始化,在程序启动时创建单例对象
Singleton Singleton::instance;

解释

  • 构造函数私有化:将 Singleton 类的构造函数声明为 private,确保外部无法直接创建该类的对象。
  • 静态成员变量:使用 static Singleton instance 存储单例对象。
  • 静态成员函数:通过 static Singleton& getInstance() 提供获取单例对象的接口。
  • 全局初始化:在程序启动时,Singleton::instance 就会被创建,因为它是静态成员,且在类外进行了定义和初始化。这保证了在程序运行的任何时刻,getInstance() 都能返回同一个对象。

2. 懒汉式单例模式(线程不安全)

class Singleton {
private:// 私有构造函数,防止外部创建对象Singleton() {}// 静态成员变量,存储单例对象static Singleton* instance;
public:// 公有静态成员函数,用于获取单例对象static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}
};// 静态成员变量的初始化,初始化为 nullptr
Singleton* Singleton::instance = nullptr;

解释

  • 构造函数私有化:与饿汉式相同,将构造函数设为 private
  • 静态指针成员变量:使用 static Singleton* instance 存储单例对象的指针,初始化为 nullptr
  • 静态成员函数getInstance() 函数在首次调用时检查 instance 是否为 nullptr,若为 nullptr 则创建对象,后续调用都将返回同一个对象。
  • 线程不安全:这种方式在多线程环境下存在问题,多个线程可能同时检查到 instance 为 nullptr,并同时创建对象,导致多个实例的出现。

3. 懒汉式单例模式(线程安全,使用互斥锁)

#include <mutex>class Singleton {
private:// 私有构造函数,防止外部创建对象Singleton() {}// 静态成员变量,存储单例对象static Singleton* instance;// 互斥锁,用于线程同步static std::mutex mtx;
public:// 公有静态成员函数,用于获取单例对象static Singleton* getInstance() {std::unique_lock<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}return instance;}
};// 静态成员变量的初始化,初始化为 nullptr
Singleton* Singleton::instance = nullptr;
// 静态成员变量的初始化,创建互斥锁
std::mutex Singleton::mtx;

解释

  • 构造函数私有化:确保外部无法直接创建对象。
  • 静态指针成员变量:存储单例对象的指针,初始化为 nullptr
  • 互斥锁:使用 std::mutex mtx 进行线程同步。
  • 静态成员函数:在 getInstance() 中,使用 std::unique_lock 获取互斥锁,确保同一时刻只有一个线程可以创建单例对象。
  • 性能问题:这种方式每次调用 getInstance() 都需要加锁,即使 instance 已经创建,会影响性能。

4. 懒汉式单例模式(线程安全,双重检查锁定)

#include <mutex>class Singleton {
private:// 私有构造函数,防止外部创建对象Singleton() {}// 静态成员变量,存储单例对象static Singleton* instance;// 互斥锁,用于线程同步static std::mutex mtx;
public:// 公有静态成员函数,用于获取单例对象static Singleton* getInstance() {if (instance == nullptr) {std::unique_lock<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}}return instance;}
};// 静态成员变量的初始化,初始化为 nullptr
Singleton* Singleton::instance = nullptr;
// 静态成员变量的初始化,创建互斥锁
std::mutex Singleton::mtx;

 解释

  • 构造函数私有化:防止外部创建对象。
  • 静态指针成员变量:存储单例对象指针,初始化为 nullptr
  • 互斥锁:用于线程同步。
  • 静态成员函数:使用双重检查锁定,第一次检查 instance 是否为 nullptr 是无锁的,若为 nullptr 则加锁再次检查并创建对象,避免了每次调用 getInstance() 都加锁的性能问题。
  • 潜在问题:在某些编译器和处理器架构下,由于指令重排,可能导致 instance 已经分配内存但未完成构造函数调用,导致其他线程访问到未完全初始化的对象。

5. 懒汉式单例模式(线程安全,C++11 及以上) 

#include <memory>
#include <mutex>class Singleton {
private:// 私有构造函数,防止外部创建对象Singleton() {}
public:// 公有静态成员函数,用于获取单例对象static Singleton& getInstance() {static std::once_flag flag;std::call_once(flag, []() {instance.reset(new Singleton());});return *instance.get();}
private:// 静态成员变量,存储单例对象static std::unique_ptr<Singleton> instance;
};// 静态成员变量的初始化,使用智能指针存储单例对象
std::unique_ptr<Singleton> Singleton::instance;

 解释

  • 构造函数私有化:防止外部创建对象。
  • 静态成员函数:使用 std::once_flag 和 std::call_once 保证单例对象只被创建一次。
  • 智能指针:使用 std::unique_ptr<Singleton> instance 存储单例对象,避免了内存管理问题。
  • C++11 特性std::call_once 是 C++11 引入的,确保 instance 只会被调用一次,且是线程安全的,解决了双重检查锁定的指令重排问题。

6、总结

通过以上几种方式,可以实现单例模式并保证全局唯一性。在实际应用中,推荐使用 C++11 及以上的 std::call_once 和 std::unique_ptr 实现,它提供了简洁、安全和高效的单例模式实现方式。


上述几种实现方式都旨在保证单例模式的全局唯一性,但各有优缺点,你可以根据实际需求和开发环境选择合适的实现方式。**代码解释**:
- **饿汉式单例模式**:- 优点:实现简单,在程序启动时就创建单例对象,保证了线程安全和全局唯一性。- 缺点:可能会造成资源浪费,因为单例对象在程序开始时就创建,无论是否使用。- **懒汉式单例模式(线程不安全)**:- 优点:单例对象在首次使用时创建,避免了资源浪费。- 缺点:在多线程环境下无法保证单例对象的唯一性,会出现多个实例。- **懒汉式单例模式(线程安全,使用互斥锁)**:- 优点:使用互斥锁保证了多线程环境下的单例对象唯一性。- 缺点:性能开销大,每次调用 `getInstance()` 都要加锁,即使单例对象已经创建。- **懒汉式单例模式(双重检查锁定)**:- 优点:在多线程环境下相对高效,避免了每次调用都加锁。- 缺点:存在指令重排的潜在风险,可能导致获取到未完全初始化的对象。- **懒汉式单例模式(线程安全,C++11及以上)**:- 优点:结合了 `std::call_once` 和 `std::unique_ptr`,既保证了线程安全,又避免了指令重排问题,是现代 C++ 推荐的实现方式。- 缺点:需要 C++11 及以上标准支持。

相关文章:

单例模式-如何保证全局唯一性?

以下是几种实现单例模式并保证全局唯一性的方法&#xff1a; 1. 饿汉式单例模式 class Singleton { private:// 私有构造函数&#xff0c;防止外部创建对象Singleton() {}// 静态成员变量&#xff0c;存储单例对象static Singleton instance; public:// 公有静态成员函数&…...

设计模式学习笔记——结构型模式

文章目录 适配器模式 Adapter适用场景UML 桥接模式 Bridge适用场景UML 组合模式 Composite装饰模式 Decorator外观模式 Facade享元模式 Flyweight代理模式 Proxy 适配器模式 Adapter 适用场景 希望使用某个类&#xff0c; 但是其接口与其他代码不兼容时&#xff0c; 可以使用…...

WEB攻防-通用漏洞_文件上传_黑白盒审计流程

目录 前置知识点 Finecms-CMS文件上传 ​编辑 Cuppa-Cms文件上传 Metinfo-CMS 文件上传 前置知识点 思路&#xff1a; 黑盒就是寻找一切存在文件上传的功能应用 1 、个人用户中心是否存在文件上传功能 2 、后台管理系统是否存在文件上传功能 3 、字典目录扫描探针文件上传构…...

RabbitMQ基本介绍及简单上手

&#xff08;一&#xff09;什么是MQ MQ&#xff08;message queue&#xff09;本质上是队列&#xff0c;满足先入先出&#xff0c;只不过队列中存放的内容是消息而已&#xff0c;那什么是消息呢&#xff1f; 消息可以是字符串&#xff0c;json也可以是一些复杂对象 我们应用场…...

服务器证书不受信任是什么问题?

用户在访问某些网站时&#xff0c;可能会遇到“服务器证书不受信任”的警告。这一问题不仅影响用户的浏览体验&#xff0c;更可能对网站的信誉和安全性产生深远影响。那么服务器证书不受信任是什么问题呢&#xff1f; 服务器证书的基本概念 服务器证书是由证书颁发机构(CA)签…...

spring mvc源码学习笔记之十

前面的文章介绍了用 WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 来代替 web.xml 。 我们学 java web 的时候就知道&#xff0c;servlet 容器会自动加载 web.xml。 那么&#xff0c;疑问就来了&#xff0c;WebApplicationInitialize…...

Ubuntu 下载安装 elasticsearch7.17.9

参考 https://blog.csdn.net/qq_26039331/article/details/115024218 https://blog.csdn.net/mengo1234/article/details/104989382 过程 来到 Es 的版本发布列表页面&#xff1a;https://www.elastic.co/downloads/past-releases#elasticsearch 根据自己的系统以及要安装的…...

Qt笔记:网络编程Tcp

一、铺垫 1.以下只是告诉诸位怎样去构建服务器与客户端&#xff1b;客户端这样构建肯定没问题&#xff1b;但是服务端不可能这样写&#xff0c;因为他是布置在Linux上的&#xff0c;纯数据类处理服务器&#xff0c;根本不可能用Qt写&#xff1b;这在Qt的http类中就表明了&…...

C++单例模式跨DLL调用问题梳理

问题案例&#xff1a; 假设有这样一个单例模式的代码 //test.h header class Test { public:static Test &instance() {static Test ins;return ins;}void foo(); };void testFoo();//test.cpp source #include "test.h"void Test::foo() {printf("%p\n&q…...

oracle闪回版本查询

闪回版本查询&#xff08;Flashback Versions Query&#xff09;是Oracle数据库提供的一种功能&#xff0c;允许用户查看某个表在特定时间范围内的所有版本。这对于审计和调试数据修改问题非常有用。通过闪回版本查询&#xff0c;你可以了解表中的数据在某个时间段内的变化历史…...

C#用winform窗口程序操作服务+不显示Form窗体,只显示右下角托盘图标+开机时自启动程序【附带项目地址】

服务的文章在:https://blog.csdn.net/weixin_43768573/article/details/144957941 一、用winform窗口程序操作服务 1、点击“创建新项目”,选择“Windows 服务(.NET Framework)” 2、给项目命名 3、右击项目->添加->新建项,选择“应用程序清单文件(仅限Windo…...

UOS系统和windows系统wps文档显示差异问题解决

最近在使用UOS系统的过程中&#xff0c;发现了一个很有意思的现象。就是在UOS系统上编辑的文档&#xff0c;发到windows系统上&#xff0c;会出现两个文档显示差异很大的情况&#xff0c;文档都是使用一样的wps软件打开的。到底是什么原因导致这种现象的呢&#xff1f;该如何解…...

JS中函数基础知识之查漏补缺(写给小白的学习笔记)

函数 函数是ECMAScript中 最有意思的部分之一, 主要是因为函数实际上是对象.-- 每个函数 都是Function类型的实例,Function也有属性和方法. 因为函数是对象,所以函数名就是指向函数对象的指针. 常用的定义函数的语法: ①函数声明 ②函数表达式 ③箭头函数 function sum (n…...

蓝桥杯训练

1对于一个字母矩阵&#xff0c;我们称矩阵中的一个递增序列是指在矩阵中找到两个字母&#xff0c;它们在同一行&#xff0c;同一列&#xff0c;或者在同一 45 度的斜线上&#xff0c;这两个字母从左向右看、或者从上向下看是递增的。 例如&#xff0c;如下矩阵中 LANN QIAO有…...

前端学习DAY33(外边距的折叠)

垂直外边距的重叠 在网页中相邻的垂直方向的外边距&#xff0c;会发生外边距的重叠 兄弟元素 兄弟元素之间的相邻外边距会取&#xff08;绝对值&#xff09;最大值&#xff0c;而不是取和&#xff0c;谁大取谁 特殊情况&#xff1a;如果相邻的外边距一正一负&#xff0c;则取两…...

asp.net core mvc的 ViewBag , ViewData , Module ,TempData

在 ASP.NET MVC 和 ASP.NET Core MVC 中&#xff0c;ViewBag 和 ViewData 是两种用于将数据从控制器传递到视图&#xff08;View&#xff09;的常用方法。它们都允许控制器将动态数据传递给视图&#xff0c;但它们的实现方式有所不同。关于 Module&#xff0c;它通常指的是某种…...

Linux驱动学习之第二个驱动程序(LED点亮关闭驱动程序-分层设计思想,使其能适应不同的板子-驱动程序模块为多个源文件怎么写Makefile)

目录 看这篇博文前请先掌握下面这些博文中的知识需要的PDF资料完整源代码board_fire_imx6ull-pro.c中的代码leddrv.c中的代码ledtest.c中的代码 程序设计思想和文件结构实现分层思想的具体方法概述具体实现分析定义结构体led_operations用来集合各个单板硬件层面操作LED的函数定…...

手写@EnableTransactionalManagement

定义一个注解&#xff0c;用于标注于方法上&#xff0c;标志着此方法是一个事务方法。 Target({ElementType.METHOD,ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface MyTransaction {}定义一个开启事务功能的注解 Component Import(TransActionBean…...

【Vue】:解决动态更新 <video> 标签 src 属性后视频未刷新的问题

问题描述 在 Vue.js 项目&#xff0c;当尝试动态更新 <video> 标签的 <source> 元素 src 属性来切换视频时&#xff0c;遇到了一个问题&#xff1a;即使 src 属性已更改&#xff0c;浏览器仍显示旧视频。具体表现为用户选择新视频后&#xff0c;视频区域继续显示之…...

网络基础1 http1.0 1.1 http/2的演进史

http1.0 1.1 http/2的演进史&#x1f60e; &#xff08;连接复用 队头阻塞 服务器推送 2进制分帧&#xff09; 概述 我们主要关注的是应用层 传输层 http协议发展历史 http的报文结构&#xff1a;起始行 Header Body http的典型特征 http存在的典型问题 Keep Alive机制 chun…...

TranslucentTB:Windows任务栏透明化改造的工程级解决方案

TranslucentTB&#xff1a;Windows任务栏透明化改造的工程级解决方案 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 当你面对Windows单调…...

UR机械臂ROS2驱动选型指南:深入对比Ethernet RTDE与EtherCAT,你的项目该怎么选?

UR机械臂ROS2驱动选型指南&#xff1a;Ethernet RTDE与EtherCAT深度对比与实战决策 在工业自动化与协作机器人领域&#xff0c;UR&#xff08;Universal Robots&#xff09;机械臂因其灵活性和易用性广受青睐。然而&#xff0c;当工程师们将UR机械臂集成到ROS2生态系统中时&…...

3种方法实现微信聊天记录完整备份:WeChatExporter的高效实用指南

3种方法实现微信聊天记录完整备份&#xff1a;WeChatExporter的高效实用指南 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 在数字时代&#xff0c;微信聊天记录承载着我…...

智能温控7级调节:ThinkPad用户的风扇噪音与性能平衡终极方案

智能温控7级调节&#xff1a;ThinkPad用户的风扇噪音与性能平衡终极方案 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 你是否经常被ThinkPad笔记本电脑在运行时突然增…...

SEO_解读最新搜索引擎算法,调整你的SEO策略

SEO:解读最新搜索引擎算法&#xff0c;调整你的SEO策略 在当今数字营销的世界里&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;始终是提升网站流量和品牌知名度的关键。每当搜索引擎更新其算法&#xff0c;SEO策略就需要相应调整。今天我们将深入解读最新的搜索引擎算法…...

Betterlockscreen缓存机制解析:为什么它比传统锁屏更快

Betterlockscreen缓存机制解析&#xff1a;为什么它比传统锁屏更快 【免费下载链接】betterlockscreen &#x1f340; sweet looking lockscreen for linux system 项目地址: https://gitcode.com/gh_mirrors/be/betterlockscreen Betterlockscreen是一款为Linux系统设计…...

电商人必备!AI净界RMBG-1.4批量处理商品图,效率提升10倍

电商人必备&#xff01;AI净界RMBG-1.4批量处理商品图&#xff0c;效率提升10倍 1. 电商人的痛点&#xff1a;每天被抠图折磨的日子 做电商的朋友&#xff0c;下面这个场景你一定不陌生&#xff1a; 早上9点&#xff0c;运营发来50张新款T恤的实拍图&#xff0c;要求今天下班…...

nli-distilroberta-base部署教程:Docker镜像免配置运行DistilRoBERTa NLI API

nli-distilroberta-base部署教程&#xff1a;Docker镜像免配置运行DistilRoBERTa NLI API 1. 项目介绍 nli-distilroberta-base是一个基于DistilRoBERTa模型的自然语言推理(NLI)Web服务。它能帮你快速判断两个句子之间的关系&#xff0c;特别适合需要分析文本逻辑关系的应用场…...

项目建议书、可研报告与初步设计方案的定位与关联

在信息化项目建设过程中&#xff0c;项目建议书、可行性研究报告&#xff08;以下简称“可研报告”&#xff09;和初步设计方案是前期工作阶段最为核心的三份文件&#xff0c;它们共同构成了项目从构想到落地的决策链条&#xff0c;承担着不同阶段的论证与规划职责。然而实际工…...

从实战出发:解析墨水屏LUT移植与局刷参数调优的通用方法论

1. 墨水屏LUT基础认知&#xff1a;从"电子墨水"到驱动逻辑 第一次拆解墨水屏驱动板时&#xff0c;我盯着那些密密麻麻的电路走线和芯片引脚直发懵。直到把屏幕泡在酒精里不小心擦掉了表面涂层&#xff0c;才真正看清"电子墨水"的微观结构——那些悬浮在液体…...