STL,智能指针和线程安全,线程安全的单例模式和懒汉饿汉的实现,以及读者写者问题

🍑个人主页:Jupiter.
🚀 所属专栏:Linux从入门到进阶
欢迎大家点赞收藏评论😊

在这里插入图片描述

在这里插入图片描述

目录

  • `📚STL,智能指针和线程安全 `
    • `📕STL中的容器是否是线程安全的?`
    • `💡智能指针是否是线程安全的?`
      • `🍁shared_ptr、unique_ptr和weak_ptr`
      • `🍑线程安全的智能指针atomic_shared_ptr`
  • `🌙线程安全的单例模式 `
            • `什么是单例模式 `
            • `什么是设计模式`
            • `单例模式的特点 `
    • `⭐饿汉实现方式和懒汉实现方式`
      • `🦅饿汉方式实现单例模式 `
      • `🦌懒汉方式实现单例模式`
      • `🐎懒汉方式实现单例模式(线程安全版本)`
  • 🐛其他常见的各种锁
            • `什么是自旋?`
  • `📚读者写者问题`
    • `🔒读写锁 `
      • 🐟系统中读写锁接口
    • 🦈读者写者优先问题:


📚STL,智能指针和线程安全

📕STL中的容器是否是线程安全的?

  • 不是.

  • 原因是, STL 的设计初衷是将性能挖掘到极致, 而一旦涉及到加锁保证线程安全, 会对性能造成巨大的影响。

  • 而且对于不同的容器, 加锁方式的不同, 性能可能也不同(例如hash表的锁表和锁桶).

  • 因此 STL 默认不是线程安全. 如果需要在多线程环境下使用, 往往需要调用者自行保证线程安全.

💡智能指针是否是线程安全的?

🍁shared_ptr、unique_ptr和weak_ptr

在C++中,常见的智能指针包括shared_ptrunique_ptrweak_ptr

  • shared_ptr:

    • shared_ptr使用引用计数机制来管理对象的生命周期。虽然它的复制构造函数和赋值操作是原子操作(这保证了智能指针本身的拷贝在多线程下是安全的),但引用计数的增加和减少通常不是原子的。这意味着,如果多个线程同时尝试增加或减少同一个shared_ptr的引用计数,而没有适当的同步机制,就可能导致数据竞争和不一致的问题。因此,在多线程环境中,直接使用shared_ptr进行共享对象的访问和修改通常不是线程安全的。如果需要在多线程中使用shared_ptr,应该使用互斥锁或其他同步机制来保护对共享资源的访问。
  • unique_ptr:

    • unique_ptr保证同一时间只有一个所有者拥有对象的所有权。由于它不允许复制(除了移动构造和移动赋值之外),因此它不会遇到与shared_ptr相同的线程安全问题。然而,如果尝试将unique_ptr传递给不同的线程,或者在多线程中修改它的所有权,仍然需要适当的同步措施来确保线程安全。
  • weak_ptr:

    • weak_ptr是一个对shared_ptr所管理的对象存在性的弱引用,它不会增加对象的引用计数。因此,weak_ptr的线程安全性问题通常与它所引用的shared_ptr的线程安全性相关。在多线程环境中,如果weak_ptr和shared_ptr一起使用,并且没有适当的同步机制,同样可能导致问题。

🍑线程安全的智能指针atomic_shared_ptr

为了解决多线程环境中智能指针的线程安全问题,C++14引入了atomic_shared_ptr。这是一个线程安全的智能指针,它使用原子操作来管理引用计数,从而避免了数据竞争的问题。然而,需要注意的是,即使使用了atomic_shared_ptr,对智能指针所指向对象的访问仍然可能需要额外的同步机制,特别是当这些访问涉及到修改对象状态时。


🌙线程安全的单例模式

什么是单例模式
  • 单例模式是一种 “经典的, 常用的, 常考的” 设计模式。
什么是设计模式

针对一些经典的常见的场景, 给定了一些对应的解决方案, 这个就是设计模式。

单例模式的特点

某些类, 只应该具有一个对象(实例), 就称之为单例。

在很多服务器开发场景中, 经常需要让服务器加载很多的数据 (上百G) 到内存中. 此时往往要用一个单例的类来管理这些数据。

⭐饿汉实现方式和懒汉实现方式

[洗完的例子]

  • 吃完饭, 立刻洗碗, 这种就是饿汉方式. 因为下一顿吃的时候可以立刻拿着碗就能吃饭.
  • 吃完饭, 先把碗放下, 然后下一顿饭用到这个碗了再洗碗, 就是懒汉方式.

饿汉方式优化将来使用的效率,以空间换时间。程序加载的时候就创建对象。

🦅饿汉方式实现单例模式

  • 只要通过 Singleton 这个包装类来使用 T 对象, 则一个进程中只有一个 T 对象的实例.
template <typename T> 
class Singleton 
{ 
public: static T* GetInstance() { return &data; } 
private:static T data; 
}; 

🦌懒汉方式实现单例模式

懒汉方式最核心的思想是 "延时加载". 从而能够优化服务器的启动速度.运行时创建对象。

template <typename T> 
class Singleton { 
public: static T* GetInstance() { if (inst == NULL) { inst = new T(); } return inst; } 
private:static T* inst; 
}; 

存在一个严重的问题, 线程不安全。
第一次调用 GetInstance 的时候, 如果两个线程同时调用, 可能会创建出两份 T 对象的实例。
但是后续再次调用, 就没有问题了。

🐎懒汉方式实现单例模式(线程安全版本)

// 懒汉模式, 线程安全 
template <typename T> 
class Singleton { volatile static T* inst; // 需要设置 volatile 关键字, 否则可能被编译器优化. static std::mutex lock; 
public: static T* GetInstance() { if (inst == NULL) {     // 双重判定空指针, 降低锁冲突的概率, 提高性能. lock.lock(); // 使用互斥锁, 保证多线程情况下也只调用一次 new. if (inst == NULL) { inst = new T(); } lock.unlock(); } return inst; } 
};

🐛其他常见的各种锁

  • 悲观锁:在每次取数据时,总是担心数据会被其他线程修改,所以会在取数据前先加锁(读锁,写锁,行锁等),当其他线程想要访问数据时,被阻塞挂起。
  • 乐观锁:每次取数据时候,总是乐观的认为数据不会被其他线程修改,因此不上锁。但是在更新数据前,会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式:版本号机制和CAS操作。
  • CAS操作:当需要更新数据时,判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不等则失败,失败则重试,一般是一个自旋的过程,即不断重试。
  • 自旋锁,公平锁,非公平锁?
  • 重复非阻塞的申请锁,称为自选,非阻塞的读取文件这个过程叫非阻塞
什么是自旋?
  • 如果一个线程申请锁成功后执行的代码很耗时(比如代码里面面有大量的io操作等),推荐线程在申请锁的时候等待挂起,如果不耗时的话,推荐让其他线程重复非阻塞的申请锁,也就是自旋

  • 自旋锁:用法和其他锁一样,不赘述。


📚读者写者问题

🔒读写锁

在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相比较改写,它们读的机会反而高的多。通常而言,在读的过程中,往往伴随着查找的操作,中间耗时很长。给这种代码段加锁,会极大地降低我们程序的效率。那么有没有一种方法,可以专门处理这种多读少写的情况呢? 有,那就是读写锁。

读写锁的伪代码:

🐟系统中读写锁接口

  • 初始化
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);

  • 销毁
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

  • 加锁和解锁
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

  • 解锁(读写共用)
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

🦈读者写者优先问题:

  • 默认的是写者优先

写者优先:当读者正在访问资源的时候,写者申请访问,这时候过后再有读者申请锁的时候,会失败,类似于会放到在一个等待队列中等待,会等当前读者读完后,写者再访问资源,访问完后这些读者才会申请锁访问资源(也就是说,如果读者挡在访问资源的时候,这时写者要访问资源,后续来的读者都会等待,等目前正在访问资源的读者退出后,读者访问完资源退出后,这些等待的读者才可以申请锁,访问资源。)

读者优先:与上面的相反。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1538165.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Threejs之看房案例(下)

本文目录 前言最终效果1、点精灵1.1 添加点精灵1.2 点精灵效果2、添加事件2.1 鼠标移动事件2.1.1 效果2.2 鼠标点击事件2.2.1 效果2.3 切换互通3. 完整代码前言 在Threejs之看房案例(上)这篇博客中我们已经完成了大厅的3d观看效果,但是我们会发现如果想去其他房间观看,没有…

使用SQL递归查询树状结构,又可以跟同事吹牛了!

前言 在关系型数据库中&#xff0c;数据通常存储为二维表格&#xff08;rows 和 columns&#xff09;。然而&#xff0c;在实际业务中&#xff0c;很多场景下我们需要处理树状结构的数据&#xff0c;例如&#xff1a; 公司组织架构&#xff1a;从某个部门开始&#xff0c;查询…

Python异常处理:自定义异常②

文章目录 1. 什么是自定义异常&#xff1f;2. 为什么需要自定义异常&#xff1f;3. 如何定义自定义异常&#xff1f;3.1 基本自定义异常3.2 带详细信息的自定义异常3.3 自定义异常的继承层次 4. 使用自定义异常4.1 抛出自定义异常4.2 捕获自定义异常 5. 自定义异常的应用场景5.…

二叉树——数据结构

这次我们来学习一下数据结构中的二叉树 1. 二叉树的概念及结构 1.1 二叉树的定义 定义&#xff1a;所有结点的度小于等于2的树。 上图中可以看出 二叉树不存在度大于2的结点二叉树的子树有左右之分&#xff0c;次序不能颠倒&#xff0c;因此二叉树是有序树。 任意二叉树都…

2024年适合培训服务企业的7款CRM盘点

培训服务行业在线索管理、客户管理、数据分析、项目管理、师资管理和课程管理等方面&#xff0c;使用CRM可以事半功倍&#xff0c;最重要的是&#xff0c;可以用数据说话&#xff0c;找到降本增效的方向。 下面对培训服务行业常用测CRM做个盘点&#xff0c;包括国内比较头部的…

米壳AI:跨境电商必备:不损失原图的图片翻译工具!

嘿&#xff0c;跨境电商的小伙伴们&#xff01; 今天来聊聊如何突破语言壁垒&#xff0c;让你的商品在国际市场上大放异彩。 随着 “一带一路” 战略的不断推进&#xff0c;跨境电商的发展势头愈发强劲。然而&#xff0c;语言障碍却成为了跨境交易中的一大难题。别担心&#x…

ppt组织结构图怎么增加分支?

在使用ppt里边的SmartArt来制作组织结构图的时候&#xff0c;我们发现里边的图形不够用&#xff0c;需要增加分支&#xff0c;这也就是大家近期问的ppt组织结构图怎么增加分支。今天设计学徒自学网小编就把具体的操作步骤分享给大家了&#xff0c;希望能帮助你们&#xff01; …

RFID技术实现消防物资消防车无感化智能管理设计方案

在消防工作中&#xff0c;物资管理的高效性与准确性直接关系到救援行动的成败&#xff0c;传统的消防物资管理方式主要依赖人工记录和定期盘点&#xff0c;这种方式存在着诸多弊端。首先&#xff0c;人工记录容易出现错误&#xff0c;数据的准确性难以保证。例如&#xff0c;在…

制作U盘安装操作系统(启动盘、系统盘、Windows、Linux)

第一种&#xff08;Windows&#xff09; 官网windows制作启动盘 1. 打开Win11下载官网 下载 Windows 11https://www.microsoft.com/zh-cn/software-download/windows11 2. 下载制作操作系统工具 这里不要下载错了 3. 启动工具 选择U盘&#xff0c;选择你的U盘即可&#xf…

TASK-CUSTOMIZEDMASKED AUTOENCODERVIA MIXTURE OF CLUSTER-CONDITIONAL EXPERTS

发表于&#xff1a;ICLR 2023 notable top 25%&#xff08;相当于spotlight) 推荐指数: #paper/⭐⭐⭐ 论文链接: Task-customized Masked Autoencoder via Mixture of Cluster-conditional Experts | OpenReview poster链接&#xff1a;ICLR 2023 Task-customized Masked Auto…

人类行为识别系统源码分享

人类行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

使用streaming-json-py插件处理JSON数据流:详细指南

目录 一、streaming-json-py简介 二、安装与配置 三、基本使用 示例1:处理不完整的JSON对象 示例2:处理不完整的JSON数组 四、高级用法 实时数据流分析 日志处理 五、性能优化与错误处理 六、总结与展望 在数据驱动的现代社会,实时处理数据流已成为许多应用和服务…

Linux·权限与工具-git与gdb

1. git工具 git是一款软件&#xff0c;发明它的人同时发明了Linux操作系统&#xff0c;也就是大名鼎鼎的Linus Torvalds 林纳斯托瓦兹。后来人们把git软件包装&#xff0c;产生了github、gitee等平台。 git产生的初衷就是便于进行多人协同管理&#xff0c;同时它还可以用来将本…

GB/T28181-2022相对老版本有哪些变动?

GB/T28181-2022新版概述 GB/T28181-2022是《公共安全视频监控联网系统信息传输、交换、控制技术要求》的国家标准&#xff0c;该标准在2022年12月30日发布&#xff0c;并于2023年7月1日正式实施。以下是关于GB/T28181-2022的详细解析&#xff1a; 一、标准概述 GB/T28181-20…

2024/9/18 模型的存储与读取

一、模型的存储与读取 主要涉及到torch.save和torch.load函数 新建两个python文件&#xff1a; 1.在model_save文件中保存模型(方式一)和模型参数(方式二) 2.在model_load文件中读取模型(方式一)和模型参数并装载模型(方式二)

海外绿色农业果蔬投资系统可以二开多语言

食品安全已经是全球非常重视&#xff0c;关于农业方面的基础建设投资都在大力推进&#xff0c;做一个绿色农业果蔬投资是一个非常不错的。希望这个系统能对你有很大的帮助&#xff01;

三菱变频器变更电流最大输入(20mA 初始值)时的频率(60Hz初始值)

变更最高频率。变更示例 在4~ 20mA 输入频率设定器中&#xff0c;将 20mA 时的频率从 60Hz(初始值)变更为 50Hz。 输入 20mA 电流时调整为输出 50Hz。 将Pr.126 设定为“50Hz” NOTE 4mV 时的频率设定可通过校正参数 C5 设定。 其他的频率设定电流增益的调整方法&#xff0c;还…

泛微E-Mobile client/cdnfile 任意文件读取漏洞复现

0x01 产品简介 泛微E-Mobile是一款由泛微网络科技股份有限公司开发的移动办公产品,该产品专门为手机、平板电脑等移动终端用户设计,旨在提供便捷、高效的移动办公体验。适用于企业高管和有移动办公需求的业务部相关员工使用,特别适合于已有内部OA系统的大中型企业机构,尤其…

HBuilder无法打开微信开发者工具

配置微信开发工具路径之后&#xff0c;HBuilder无法打开微信开发者工具 使用HBuilder打开微信开发者工具的配置&#xff0c;官网有 运行至微信模拟器控制台报错 这个时候就需要打开微信开发者工具进行安全设置了

国外问卷调查怎么做的,新手怎么开始?

既然你准备进入这个行业&#xff0c;就应该明白一件事&#xff1a;这个项目&#xff0c;本质就是网络搬砖。 也就是你搬的越多、越快&#xff0c;就赚得越多。 做一份问卷&#xff0c;比如2美元&#xff0c;做50份&#xff0c;就是100美元&#xff0c;也就是700元左右。 月入…