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

【线程安全的单例模式和STL是否是线程安全/智能指针是否是线程安全】

文章目录

  • 一、单例模式的特点
  • 二、饿汉模式实现单例
  • 三、懒汉模式实现单例
  • 四、STL线程安全吗?
  • 五、智能指针线程安全吗?


一、单例模式的特点

一个类,只应该实例化了一个对象,就是单例。

二、饿汉模式实现单例

举个饿汉模式的例子:洗碗,一个人吃碗饭之后,他马上洗碗,下次吃饭的时候就可以直接拿起碗吃饭了。这就是饿汉模式。
懒汉模式是:一个人吃完饭之后,他先不洗碗,下次吃饭的时候再洗碗,这就是懒汉模式。
懒汉模式的核心特点是:延迟加载。

饿汉模式实现单例:
template<class T>
class Singleton
{
private:
	static T inst;

public:
	static T* GetInstance()
	{
		return &inst;
	}
};

通过SingleTon类实例化的对象只能拥有一个。

三、懒汉模式实现单例

懒汉模式具体是什么已经介绍过了。
下面用代码实现懒汉模式

懒汉模式实现单例
template<class T>
class Singleton
{
private:
	static T* inst;

public:
	static T* GetInstance()
	{
		if(inst == nullptr)
			inst  = new T();
			
		return inst;
	}
};

但是这样的懒汉模式存在线程安全,假如有两个线程同时进入GetInstance函数中new T()呢?
这样就会存在两个inst指针指向的对象了, 就不再是单例了。

所以需要加锁保证线程安全。
下面是线程安全版本的单例模式

template <class T>
class Singleton
{
private:
	static std::mutex lock;
	volatile static T* inst;  //设置volatile关键字的目的是防止被编译器优化
public:
	static T* GetInstance()
	{
		lock.lock();
		if(inst == nullptr)		//判断的本质也是再访问临界资源,所以要在加锁之后
			inst = new T();
		lock.unlock();
		return inst;
	}

这样解决了线程并发问题,但是这样假如有大量线程同时进入该函数时,会并发竞争锁,会造成性能低下,极端情况下可能出现卡顿现象。
因为不管有没有实例化T对象,都会进行锁竞争,这是不太合理的。

正确的应该是:如果没有实例化T对象,先申请锁对T对象new一个出来。
如果有了T对象,直接返回即可。
下面是改正后的代码:

template <class T>
class Singleton
{
private:
	static std::mutex lock;
	volatile static T* inst;  //设置volatile关键字的目的是防止被编译器优化
public:
	static T* GetInstance()
	{
		if(inst == nullptr)   //双重判定空指针, 降低锁冲突的概率, 提高性能
		{
			lock.lock();
			if(inst == nullptr)   //判断的本质也是再访问临界资源,所以要在加锁之后
				inst = new T();
			lock.unlock();
		}
		return inst;
	}
	

};

这样实现懒汉模式的单例模式,解决了线程安全+性能低下的问题。

四、STL线程安全吗?

不是
原因是, STL 的设计初衷是将性能挖掘到极致, 而一旦涉及到加锁保证线程安全, 会对性能造成巨大的影响.而且对于不同的容器, 加锁方式的不同, 性能可能也不同(例如hash表的锁表和锁桶).
因此 STL 默认不是线程安全. 如果需要在多线程环境下使用, 往往需要调用者自行保证线程安全

五、智能指针线程安全吗?

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

相关文章:

  • AXIOM —— 介绍
  • ai-by-hand-excel: 用 Excel 手搓各种 AI 算法和模型
  • CSS3:深度解析与实战应用
  • 2.5.3 windows编程iocp
  • 【MATLAB例程】交互式多模型(IMM),模型使用:CV,CT左转、CT右转,二维平面,三个模型的IMM,滤波使用EKF。订阅专栏后可查看代码
  • MD2Card(markdown)
  • 打字时候选如何向后翻页?
  • 前端使用vue,一个项目从零开始开发大概构思
  • 【新能源汽车温度采集与控制系统设计深度解析】
  • 2.3 高阶导数
  • 玩转python: 掌握Python常用库之数据分析pandas
  • 【第二月_day7】Pandas 简介与数据结构_Pandas_ day1
  • kafka删除/创建 topic报错,如何解决
  • Go常见问题与答案笔记(上)
  • 如何给poco f4(redmi k40s)刷入twrp或orange fox
  • 解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式
  • 在 Ubuntu 中配置开机自启动脚本并激活 Anaconda 环境
  • 【GoLang】调用llm时提示词prompt的介绍以及使用方式
  • 玄机-第五章 linux实战-CMS01的测试报告
  • 【拒绝算法PUA】LeetCode 2255. 统计是给定字符串前缀的字符串数目
  • 戴上XR头盔,五一假期在上海也能体验“登陆月球”
  • 200枚篆刻聚焦北京中轴线,“印记”申遗往事
  • 制定出台民营经济促进法有何重大意义?全国人大常委会法工委回应
  • 俄伏尔加格勒机场正式更名为斯大林格勒机场
  • 光明网评“泉州梦嘉商贸楼不到5年便成危楼”:监管是否尽职尽责?
  • 民营经济促进法出台,自今年5月20日起施行