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

news2024/9/21 20:03:53
🍑个人主页: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.coloradmin.cn/o/2144591.html

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

相关文章

【C语言零基础入门篇 - 7】:拆解函数的奥秘:定义、声明、变量,传递须知,嵌套玩转,递归惊艳

文章目录 函数函数的定义与声明局部变量和全局变量、静态变量静态变量和动态变量函数的值传递函数参数的地址传值 函数的嵌套使用函数的递归调用 函数 函数的定义与声明 函数的概念&#xff1a;函数是C语言项目的基本组成单位。实现一个功能可以封装一个函数来实现。定义函数的…

图片转PDF技巧揭秘:四款高效工具推荐!

在数字化办公和学习的今天&#xff0c;将图片或其他文件格式转换为PDF已成为一种常见需求。以下是几款推荐的转换工具&#xff0c;它们各自具有独特的功能和使用体验&#xff0c;可帮助大家轻松实现图片转PDF及其他PDF相关操作。 福昕PDF转换大师&#xff08;365客户端&#x…

关于 Qt运行加载内存较大崩溃添加扩大运行内存 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/142341544 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

【重学 MySQL】三十三、流程控制函数

【重学 MySQL】三十三、流程控制函数 IF函数IFNULL函数CASE函数总结 在MySQL中&#xff0c;流程控制函数是用于在SQL查询、存储过程或函数中根据特定条件执行不同流程的重要工具。这些函数可以帮助我们实现复杂的逻辑判断和数据转换。 IF函数 IF函数是MySQL中最基本的流程控制…

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

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

算法-排序算法(冒泡选择插入希尔快速归并堆)

1.算法概述 1.1什么是算法 算法是特定问题的求解步骤的描述&#xff0c;是独立存在的一种解决问题的思想和方法。对于算法而言计算机编程语言并不重要&#xff0c;可以用任何计算机编程语言来编写算法。 程序数据结构算法 1.2数据结构和算法的区别和联系 数据结构只是静态…

闲置物品交易系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;卖家管理&#xff0c;广场管理&#xff0c;商品类型管理&#xff0c;商品信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;广场&#xff0c;商…

欧盟禁用PFAS材料!线材该如何应对?

了应对欧盟即将在2027年1月开始强制执行禁用PFAS材料的法规&#xff0c;一众线材厂商纷纷研发出了对应的替代材料&#xff0c;第二十三届华东磁性元件峰会现场&#xff0c;多家线材企业均带来了PFAS材料的替代产品。 宇盛电子 苏州宇盛电子有限公司&#xff08;下称“宇盛电子…

从Profinet到Ethernet IP网关技术重塑工业网络,数据传输更流畅

Profinet转Ethernet IP网关在未来工业领域可能产生以下重要影响并发挥关键作用&#xff1a;促进工业设备集成与互操作性&#xff1a;打破协议壁垒&#xff1a;在工业场景中&#xff0c;存在多种不同的工业以太网协议&#xff0c;设备往往因协议差异而难以直接通信。 Profinet转…

基于姿态估计的翻墙动作识别系统(姿态估计 mediapipe )

基于姿态估计的翻越动作识别系统是一个结合了计算机视觉、姿态估计技术和深度学习的项目&#xff0c;其目的是识别特定的动作&#xff0c;比如“翻越”动作。在这个项目中&#xff0c;我们使用MediaPipe姿态估计工具进行人体姿态估计&#xff0c;并结合深度学习模型来识别翻越动…

城市内涝积水监测预警系统助力智慧城市应急防汛

一、方案背景 近 20 年来&#xff0c;我国城市化进程加快&#xff0c;城市地区由于人口密集&#xff0c;物资财产密度不断加大等特点&#xff0c;高强度暴雨积水形成的洪涝灾害对城市化地区产生的威肋和带来的损失越来越大。由于城市的不断扩建&#xff0c;使工业区、商业区和居…

施耐德EcoStruxure Machine SCADA Expert(EMSE)用户管理进阶(十四)

之前简单介绍了用户管理的功能,这里详细展示要实现一套完整的用户管理功能需要做什么 如下图所示 符合GMP的用户管理功能一般可包含如下功能: 用户新建、用户密码修改、用户锁定/激活、用户删除、用户组策略配置(右下角可配置参数) 首先新建变量—结构体 1.cUser 2.cUser…

java日志框架之JUL(Logging)

文章目录 一、JUL简介1、JUL组件介绍 二、Logger快速入门三、Logger日志级别1、日志级别2、默认级别info3、原理分析4、自定义日志级别5、日志持久化&#xff08;保存到磁盘&#xff09; 三、Logger父子关系四、Logger配置文件 一、JUL简介 JUL全程Java Util Logging&#xff…

OSG开发笔记(三十):OSG加载动力学仿真K模型文件以及测试Demo

​ 若该文为原创文章&#xff0c;未经允许不得转载 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/142340138 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 长沙红胖子Q…

地大信息-基础信息平台 GetImg 任意文件读取漏洞复现

0x01 产品简介 地大信息的基础信息平台,通过整合各类空间基础数据,包括地理、地质、气象等多源信息,构建了一个空-天-地一体化的自然灾害监测物联网和时空感知大数据平台。该平台不仅支持数据的集成、管理和共享,还提供了丰富的数据分析和应用服务,为政府决策、行业监管和…

C++对C的扩充

练习&#xff1a;提示输入字符串&#xff0c;统计字符串中空格&#xff0c;大写字母&#xff0c;小写字母&#xff0c;其他字符的个数 #include <iostream>using namespace std;int main() {cout << "请输入字符串&#xff1a;";string str;getline(cin…

[OpenCV] 数字图像处理 C++ 学习——14霍夫变换直线、圆检测 附完整代码

文章目录 前言1.霍夫变换原理(1)霍夫变换检测直线的原理(2)霍夫变换检测圆的原理 2.代码实现(1)霍夫直线检测(2)霍夫圆检测 3.完整代码 前言 霍夫变换是一种有效的检测图像中的几何形状&#xff08;如直线、圆等&#xff09;的算法。霍夫变换通过将几何形状的检测问题转化为参…

微分方程学习笔记

文章目录 一、基础概念二、重要结论1、一阶可分离变量的微分方程求解思路2、一阶非齐次线性微分方程解的结构3、可降阶的高阶微分方程4、线性微分方程解的结构1. 二阶齐次线性微分方程解的结构2. 二阶非齐次线性微分方程解的结构 参考 之前大学的时候学微分方程有点云里雾里的&…

【2024】前端学习笔记7-颜色-位置-字体设置

学习笔记 1.定义&#xff1a;css2.颜色&#xff1a;color3.字体相关属性&#xff1a;font3.1.字体大小&#xff1a;font-size3.2.字体风格&#xff1a;font - style3.3.字体粗细&#xff1a;font - weight3.4.字体族&#xff1a;font - family 4.位置&#xff1a;text-align 1.…

CMA第三方软件测试报告获取指南

在当今竞争激烈的市场环境中&#xff0c;企业对于产品质量的重视程度不断提高。为了确保软件产品的性能和安全性&#xff0c;许多企业开始寻求专业的第三方测试服务来获取第三方软件测试报告&#xff0c;而有无CMA认证资质对于软件测试报告来说至关重要。 CMA认证是中国国家认…