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

【Linux多线程】线程安全的单例模式

文章目录

  • 1. 单例模式 与 设计模式
    • 1.1 单例模式
    • 1.2 设计模式
    • 1.3 饿汉实现模式 与 懒汉实现模式
    • 1.4 饿汉模式
      • ① 饿汉模式的特点
      • ② 饿汉式单例模式的实现
      • ③ 饿汉式单例模式的优缺点
      • ④ 适用场景
    • 1.5 懒汉模式
      • ① 懒汉式单例模式的特点
      • ② 懒汉式单例模式的实现
      • ③ 懒汉式单例模式的优缺点
      • ④ 适用场景
  • 2. 智能指针 与 线程安全
    • 2.1 STL的容器是否是线程安全?
    • 2.2 智能指针是否是线程安全?

1. 单例模式 与 设计模式

1.1 单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类在整个应用程序中只有一个实例,并提供一个全局访问点来访问这个实例。这个模式适用于那些只需要一个实例来控制整个系统的场景,如配置管理、日志记录等。

关键特性:

  • 唯一性:确保类只有一个实例,避免多实例带来的资源浪费和状态不一致。
  • 全局访问:提供一个全局访问点,使得应用程序中的所有代码能够方便地访问这个唯一实例。
  • 延迟实例化:实现延迟实例化,即仅在第一次访问时创建实例,从而节省资源并提高启动效率。

典型实现(线程安全的单例模式):

class Singleton {
public:static Singleton& getInstance() {static Singleton instance; // 局部静态变量保证实例唯一性return instance;}// 删除拷贝构造函数和赋值运算符以防止复制Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() {} // 私有构造函数以防止外部创建实例
};

1.2 设计模式

设计模式(Design Pattern)是面向对象设计中的一种标准化、经过验证的解决方案,用于解决常见的设计问题。

设计模式的类型

  1. 创建型模式:关注对象的创建过程。常见的有:

    • 单例模式(Singleton)
    • 工厂模式(Factory Method)
    • 抽象工厂模式(Abstract Factory)
    • 原型模式(Prototype)
    • 建造者模式(Builder)
  2. 结构型模式:关注类和对象如何组合成更大的结构。常见的有:

    • 适配器模式(Adapter)
    • 装饰器模式(Decorator)
    • 代理模式(Proxy)
    • 桥接模式(Bridge)
    • 组合模式(Composite)
    • 外观模式(Facade)
    • 享元模式(Flyweight)
  3. 行为型模式:关注对象之间的交互和责任分配。常见的有:

    • 观察者模式(Observer)
    • 策略模式(Strategy)
    • 状态模式(State)
    • 责任链模式(Chain of Responsibility)
    • 迭代器模式(Iterator)
    • 访问者模式(Visitor)
    • 模板方法模式(Template Method)
    • 命令模式(Command)
    • 解释器模式(Interpreter)
    • 中介者模式(Mediator)
    • 备忘录模式(Memento)

设计模式的目的:

  • 提高代码复用:通过采用通用的解决方案,减少代码重复,提高复用性。
  • 提高代码可维护性:设计模式提供了清晰的结构,使得代码更易于理解和维护,提升了整体可维护性。
  • 解决常见问题:设计模式为常见的设计问题提供了经过验证的解决方案,帮助开发人员更高效地解决问题。

1.3 饿汉实现模式 与 懒汉实现模式

单例模式分为饿汉实现 与 懒汉实现两种,简单举个例子:

饿汉方式:吃完饭,立刻洗碗;下一顿吃的时候可以立刻拿着碗就能吃饭.(确保资源随时可以使用)
懒汉方式:吃完饭, 先把碗放下, 然后下一顿饭用到这个碗了再洗碗(节省了不必要的操作,优化速度)

接下来我们对这两种单例实现模式进行解释:


1.4 饿汉模式

饿汉模式 在类被加载时就立即创建实例,而不是在第一次需要实例时才创建。这种方式的特点是实例创建时机早,通常用于资源不多且创建实例开销较小的情况。


① 饿汉模式的特点

  1. 立即实例化:类加载时就创建单例实例,不管是否有其他地方需要这个实例。
  2. 线程安全:由于实例在类加载时就创建好了,线程安全问题得到了天然的解决。
  3. 浪费资源:如果单例对象的创建开销较大,而实际运行时不一定会使用这个实例,则会浪费资源。

② 饿汉式单例模式的实现

下面是饿汉实现的单例模式的示例( C++ ):

class Singleton {
public:// 提供全局访问点static Singleton& getInstance() {return instance; // 直接返回已经创建好的实例}// 删除拷贝构造函数和赋值运算符以防止复制Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:// 构造函数是私有的,以防止外部创建实例Singleton() {}// 静态成员变量,类加载时就创建实例static Singleton instance;
};// 在类外定义静态成员变量
Singleton Singleton::instance;

③ 饿汉式单例模式的优缺点

优点:

  • 线程安全:由于实例在程序启动时即被创建,因此不需要额外的同步机制来确保线程安全。
  • 简单易用:实现过程简单,易于理解和使用。

缺点:

  • 资源浪费:即使在程序运行过程中不需要这个单例实例,也会在启动时创建,可能导致资源浪费。
  • 不适合大开销对象:对于实例化开销较大的对象,预创建可能导致不必要的资源消耗。

④ 适用场景

  • 实例化对象开销较小且必定会被使用。
  • 对线程安全要求较高,且不介意在应用启动时立即创建实例。

1.5 懒汉模式

懒汉模式(Lazy Initialization) 是一种单例模式的实现方式,它在第一次需要实例时才创建对象。这种方式的特点是推迟实例化,从而避免不必要的资源消耗。

① 懒汉式单例模式的特点

  • 延迟实例化:对象仅在第一次被请求时才进行创建,从而提高了程序的效率。
  • 资源节省:在不需要实例的情况下,避免了资源的浪费,优化了资源使用。
  • 线程安全问题:在多线程环境下,可能需要额外的同步机制来确保线程安全,确保实例的唯一性。

② 懒汉式单例模式的实现

下面是懒汉模式的实现( C++ ):

#include <mutex>class Singleton {
public:// 提供全局访问点static Singleton* getInstance() {if (!instance) { // 如果实例尚未创建std::lock_guard<std::mutex> guard(mutex); // 加锁if (!instance) { // 再次检查以避免多线程下的重复创建instance = new Singleton(); // 创建实例}}return instance;}// 删除拷贝构造函数和赋值运算符以防止复制Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:// 构造函数是私有的,以防止外部创建实例Singleton() {}// 静态成员变量,保存单例实例static Singleton* instance;// 互斥锁,保护实例化过程static std::mutex mutex;
};// 在类外定义静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

③ 懒汉式单例模式的优缺点

优点:

  • 节省资源:实例仅在实际需要时创建,从而避免了不必要的资源消耗。
  • 延迟加载:能够提升程序启动速度,尤其在创建单例对象开销较大的情况下尤为显著。

缺点:

  • 线程安全问题:在多线程环境下,可能需要额外的同步机制,如使用互斥锁(mutex),以避免竞态条件。
  • 实现复杂度:比起饿汉式单例实现更复杂,需要处理多线程环境下的同步问题。

④ 适用场景

  • 实例化开销较大或不一定需要使用实例时。
  • 需要延迟加载,优化资源使用。

2. 智能指针 与 线程安全

2.1 STL的容器是否是线程安全?

不是!

  1. STL 的设计初衷是尽可能的利用性能,进行高效的编码,一旦涉及到加锁保证线程安全, 会对性能造成巨大的影响.
  2. 对于不同的容器,加锁方式的不同,性能可能也不同(如hash表的锁表和锁桶)
  3. 因此 STL 默认不是线程安全. 如果需要在多线程环境下使用, 往往需要调用者自行保证线程安全

2.2 智能指针是否是线程安全?

  • 对于 unique_ptr,其只在当前代码块范围内生效, 因此不涉及线程安全问题.
  • 对于 shared_ptr, 多个对象需要共用一个引用计数变量,存在线程安全问题,但标准库实现时考虑到了该问题,基于原子操作(CAS)的方式保证 shared_ptr 能够高效, 原子的操作引用计数

相关文章:

【Linux多线程】线程安全的单例模式

文章目录 1. 单例模式 与 设计模式1.1 单例模式1.2 设计模式1.3 饿汉实现模式 与 懒汉实现模式1.4 饿汉模式① 饿汉模式的特点② 饿汉式单例模式的实现③ 饿汉式单例模式的优缺点④ 适用场景 1.5 懒汉模式① 懒汉式单例模式的特点② 懒汉式单例模式的实现③ 懒汉式单例模式的优…...

基于jqury和canvas画板技术五子棋游戏设计与实现(论文+源码)_kaic

摘 要 网络五子棋游戏如今面临着一些新的挑战和机遇。一方面&#xff0c;网络游戏需要考虑到网络延迟和带宽等因素&#xff0c;保证游戏的实时性和稳定性。另一方面&#xff0c;网络游戏需要考虑到游戏的可玩性和趣味性&#xff0c;以吸引更多的玩家参与。本文基于HTML5和Canv…...

指针 (四)

一 . 指针的使用和传值调用 &#xff08;1&#xff09;strlen 的模拟实现 库函数 strlen 的功能是求字符串长度&#xff0c;统计的是字符串中 \0 之前的字符个数&#xff0c;函数原格式如下&#xff1a; 我们的参数 str 接收到一个字符串的起始地址&#xff0c;然后开始统计…...

便利店(超市)管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图详细视频演示技术栈系统测试为什么选择我官方认证玩家&#xff0c;服务很多代码文档&#xff0c;百分百好评&#xff0c;战绩可查&#xff01;&#xff01;入职于互联网大厂&#xff0c;可以交流&#xff0c;共同进步。有保障的售后 代码参考数据库参…...

Excel中的“块”操作

在Excel中&#xff0c;有offset、index、indirect三个对“区域”操作的函数&#xff0c;是较高版本Excel中“块”操作的利器。 (笔记模板由python脚本于2024年08月20日 19:25:21创建&#xff0c;本篇笔记适合喜欢用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Pytho…...

yolo V8训练 长条状目标

1、说明 目标数据集合中有很多长条状图片&#xff0c;如果直接Resize 会严重拉伸&#xff0c;因此采用把长条图像裁剪成2段&#xff0c;然后将裁剪后的2段图片拼接在一起。 2、代码 2.1 C 代码 &#xff08;部署&#xff0c;模型推理时C &#xff09; #include <stdio.h…...

数据结构与算法 - 设计

1. LRU缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0…...

62 网络设备的暗藏的操控者SNMP

一 SNMP 简介 SNMP(Simple Network Management Protocol,简单网络管理协议)广泛用于网络设备的远程管理和操作。SNMP允许管理员通过NMS对网络上不同厂商、不同物理特性、采用不同互联技术的设备进行管理,包括状态监控、数据采集和故障处理。 二 SNMP 网络架构 NMS(Netwo…...

华硕飞行堡垒键盘全部失灵【除电源键】

华硕飞行堡垒FX53VD键盘全部失灵【除电源键】 前言一、故障排查二、发现问题三、使用方法总结 前言 版本型号&#xff1a; 型号 ASUS FX53VD&#xff08;华硕-飞行堡垒&#xff09; 板号&#xff1a;GL553VD 故障情况描述&#xff1a; 键盘无法使用&#xff0c;键盘除开机键外…...

前端字符串将其分割成长度为 32 的子字符串数组

技巧分享&#xff1a;将字符串切割后&#xff0c;对list数据进行数据处理 要实现这个需求&#xff0c;可以编写一个简单的 JavaScript 函数来处理字符串并将其分割成长度为 32 的子字符串数组。下面是一个具体的实现示例&#xff1a; function splitStringIntoChunks(str) {l…...

小学二年级数学精选试题

小学二年级数学精选试题...

练习题 - 探索正则表达式re功能

在编程的世界里,正则表达式(Regular Expression, 简称re)是一种强大的工具,它能帮助我们有效地处理文本数据。从简单的查找到复杂的字符串操作,正则表达式都能轻松应对。特别是在数据清理、文本分析以及自动化处理等场景中,正则表达式更是不可或缺的利器。本篇文章将深入…...

【Oracle 11G 配置使用教程1】

Oracle11G配置使用教程1 引言图像方式创建数据库一、打开 Database Configuration Assistant二、创建数据库操作三、选择数据库模版四、配置数据库标识五、配置数据库标识六、创建数据库 配置监听一、打开创建监听程序二、打开创建监听程序三、重新配置监听程序四、选择监听程序…...

【ubuntu24.04】docker pull 配置

Docker 镜像加速器 的方式,看起来不行。阿里云的要先登录。手动拉取tar包的方式,官方dockerhub看起来本身没提供。docker pull 的 代理与 环境变量的代理不同因此,docker pull gitlab/gitlab-ce:17.3.0-ce.0 使用了全局代理也会失败参考官方文档: Use a proxy server with …...

《机器学习》—— 通过下采样方法实现银行贷款分类问题

文章目录 一、什么是下采样方法&#xff1f;二、通过下采样方法实现银行贷款分类问题三、下采样的优缺点 一、什么是下采样方法&#xff1f; 机器学习中的下采样&#xff08;Undersampling&#xff09;方法是一种处理不平衡数据集的有效手段&#xff0c;特别是在数据集中某些类…...

Synchronized重量级锁原理和实战(五)

在JVM中,每个对象都关联这一个监视器,这里的对象包含可Object实例和Class实例.监视器是一个同步工具,相当于一个凭证,拿到这个凭证就可以进入临界区执行操作,没有拿到凭证就只能阻塞等待.重量级锁通过监视器的方式保证了任何时间内只允许一个线程通过监视器保护的临界区代码. …...

linux常用网络工具汇总三

linux常用网络工具汇总 6. 抓包工具6.1 wireshark安装界面介绍使用过滤器TCP协议示例关于wireshark的缺点 6.2 tcpdump命令格式关键字使用关于tcpdump的缺点 6.3 fiddler6.4 burpsuite 6. 抓包工具 6.1 wireshark Wireshark&#xff08;前称Ethereal&#xff09;是一个网络封…...

Linux中nano编辑器详解

nano 是一个简单的文本编辑器&#xff0c;通常预装在大多数 Linux 发行版中。它非常适合初学者使用&#xff0c;因为它有一个用户友好的界面和易于理解的命令集。下面是对 nano 编辑器的详细说明。 启动 nano 要启动 nano 并打开一个文件进行编辑&#xff0c;你可以在终端中输…...

26-vector arraylist和linkedlist的区别

‌Vector, ArrayList, 和 LinkedList 是Java中常见的三种列表实现&#xff0c;它们各自具有不同的特点和适用场景。‌ ‌同步性与线程安全‌&#xff1a; ‌Vector‌ 是同步的&#xff0c;即线程安全的&#xff0c;它的所有方法都是同步的&#xff0c;可以由两个线程安全地访问…...

20-redis穿透击穿雪崩

Redis中的缓存穿透、‌缓存击穿和缓存雪崩是三种常见的缓存问题&#xff1a;‌ 缓存穿透&#xff1a;‌指缓存和数据库中都没有的数据&#xff0c;‌但用户还是源源不断地发起请求&#xff0c;‌导致每次请求都会直接访问数据库&#xff0c;‌从而可能压垮数据库。‌缓存击穿&…...

用仓颉语言搞定编译原理实验:从正则表达式到DFA的保姆级实现(附完整代码)

用仓颉语言实现编译原理实验&#xff1a;从正则表达式到DFA的实战指南 第一次接触编译原理实验时&#xff0c;看着那些晦涩的算法描述和数学符号&#xff0c;我完全不知道如何下手。直到用仓颉语言完整实现了从正则表达式到NFA再到DFA的转换过程&#xff0c;才真正理解了这些概…...

告别锁相误差!基于DSOGI的正负序分离在Simulink中的建模与仿真全攻略

告别锁相误差&#xff01;基于DSOGI的正负序分离在Simulink中的建模与仿真全攻略 电力电子系统的核心挑战之一&#xff0c;是如何在电网电压不平衡条件下实现精确的相位同步。去年参与某微电网项目时&#xff0c;我们团队曾因传统锁相环在电压跌落时产生的相位抖动损失了关键数…...

根据应用场景TongWeb版本选购指南

TongWeb7.0.4企业版TongWeb8.0/7.0.8企业版&#xff08;主推&#xff09;TongWeb7.0.E/8.0.E嵌入版TongHttpServer(THS)应用开发语言JavaEE应用JavaEE/JakartaEE应用JavaEE/JakartaEE应用PHP应用、vue前端应用说明&#xff1a;1. PHP应用直接推荐THS。2. .NET Core应用不需要中…...

大模型开发避坑:彻底理清 Skill(技能)与 MCP(模型 上下文协议)的本质区别与协同

在目前的 AI 应用开发圈子里&#xff0c;各种新名词层出不穷&#xff1a;Skill&#xff08;技能&#xff09;、Plugin&#xff08;插件&#xff09;、Function Calling&#xff08;函数调用&#xff09;、Tool&#xff08;工具&#xff09;、MCP&#xff08;模型上下文协议&…...

FanControl终极指南:如何免费掌控电脑风扇,告别噪音困扰

FanControl终极指南&#xff1a;如何免费掌控电脑风扇&#xff0c;告别噪音困扰 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHu…...

CW32L012FOC开源项目推进

作为一枚合格的“职场摸鱼学”实践者&#xff08;手动狗头&#xff09;&#xff0c;我坚决不建议在长假结束后立刻全身心扎进任务清单。那太不“可持续发展”了。 所以&#xff0c;今天上午&#xff0c;我可以理直气壮地把“整理工位”作为最高优先级。说得具体点&#xff0c;…...

在Windows上直接安装Android应用:APK-Installer完整使用指南

在Windows上直接安装Android应用&#xff1a;APK-Installer完整使用指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经想在Windows电脑上运行Android应用&…...

VCNL4020 proximity与环境光传感器集成设计指南

1. VCNL4020传感器技术解析&#xff1a;面向嵌入式系统的 proximity 与环境光一体化解决方案VCNL4020 是 Vishay 公司推出的高集成度光学传感芯片&#xff0c;专为资源受限的嵌入式系统设计。其核心价值在于将红外发射器&#xff08;IRED&#xff09;、接近检测光电二极管、环境…...

基于NLP-StructBERT的智能客服语义匹配实战:Java微服务集成

基于NLP-StructBERT的智能客服语义匹配实战&#xff1a;Java微服务集成 你有没有遇到过这种情况&#xff1f;用户问“我的订单怎么还没发货”&#xff0c;而你的知识库里只有“订单发货状态查询”这样的标准问题。传统的关键词匹配&#xff0c;比如搜索“订单”和“发货”&…...

Qt VS Tools配置全攻略:从安装到解决‘No Qt version assigned‘错误

Qt开发环境配置实战&#xff1a;从工具链搭建到疑难解析 Visual Studio作为主流的集成开发环境&#xff0c;与Qt框架的结合为C开发者提供了强大的生产力工具组合。但在实际项目配置过程中&#xff0c;"No Qt version assigned"这类基础错误却频繁困扰着开发者。本文…...