shared_ptr 的线程安全性

news2024/9/22 11:36:48

 多线程环境下,调用不同的 shared_ptr 实例的成员函数是不需要额外的同步手段的,即使这些 shared_ptr 管理的是相同的对象。


 多线程对于同一个 shared_ptr 实例的读操作(访问)可以保证线程安全;但对于同一个 shared_ptr 实例的写操作(改变一个 shared_ptr 指向的对象)则需要同步,否则会发生 race condition。即 shared_ptr 的引用计数本身是线程安全且无锁的,但 shared_ptr 对象本身的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化
  • 多个线程可以同时读取一个 shared_ptr 对象;

  • 多个线程同时读写一个 shared_ptr 对象,则需要加锁。

 以上讨论是 shared_ptr 对象本身的线程安全级别,而非其管理的对象的安全级别,shared_ptr 所管理的对象的并发操作是否为线程安全的,取决于具体所管理的对象,必要时需要使用一些同步手段加以保证。


#### shared_ptr 的数据结构  shared_ptr 是引用计数型智能指针,计数值保存在堆上动态分配的内存中。具体而言,`shared_ptr`包含两个成员,一个是 Foo 类型的指针,指向被管理的对象;一个 ref_count 指针,指向堆上的控制块:
 由于 shared_ptr 间的拷贝涉及两个成员的复制,而这两步拷贝不会原子性地发生: - 步骤 1:复制 ptr 指针:
  • 步骤 2:复制 ref_count 指针,并递增引用计数(此递增为线程安全的):



多线程读 shared_ptr 是安全的

 一个全局的 shared_ptr:

shared_ptr<Foo> global_ptr;

 线程 1 到 N 运行:

void threadFunc(){
	shared_ptr<Foo> local = global_ptr;
}

 以上对于 shared_ptr 变量global的读取操作是线程安全的。



多线程无保护读写 shared_ptr 可能出现的 race condition

 而要写入一个 shared_ptr(即修改一个 shared_ptr 变量),由于涉及到对象的析构,则有可能带来 race condition。


 考虑以下场景,有三个 shared_ptr:
shared_ptr<Foo> g(new Foo);		// 线程间共享的 shared_ptr 对象
shared_ptr<Foo> x;		// 线程 A 的局部变量
shared_ptr<Foo> n(new Foo);		// 线程 B 的局部变量

 初始状态:

 线程 A 执行 x = g(即 read g),并完成了步骤 1,但还没来得及执行步骤 2。此时切换到了线程 B:
 同时线程执行 g = n(即 write g),并完成了两个步骤:  先是步骤 1:
 再是步骤 2:
 此时修改 g 的 ref_count 指针,引用计数递减为 0,触发 Foo1 对象的销毁,x.ptr 成了空悬指针。

 最后回到线程 A,完成步骤 2:
 多线程无保护地读写 g,造成了 x 指针的空悬,这也是多线程读写同一个 shared_ptr 必须加锁的原因。

 当然 race condition 远不止这一种,其他线程交织有可能造成其他错误。

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

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

相关文章

对标世界一流|从Just in time到Just in case ——汽车行业供应链管理经验借鉴

01 丰田汽车精益生产 作为最复杂和最成熟的供应链之一&#xff0c;汽车行业供应链无疑是供应链领域集大成者&#xff0c;而提起汽车行业供应链&#xff0c;就不得不提到丰田汽车&#xff1b;提到丰田汽车&#xff0c;就肯定离不开大名鼎鼎的精益生产以及JIT模式。 JIT模式由丰…

【UE】高级载具插件-05-扫描材质

效果 步骤 1. 首先创建一个材质 再创建一个材质参数集 创建材质实例 2. 将后期处理体积放入场景&#xff0c;并缩放至合适的大小使其全方位覆盖 在后期处理材质中添加一个数组 选择资产引用 将材质实例拖入 3. 打开参数集&#xff0c;添加一个数组元素 设置默认值和参数名 4. …

2023年湖北省中级职称评审申报条件是什么呢?学历不够可以申报吗?

2023年湖北省中级职称评审申报条件是什么呢&#xff1f;学历不够可以申报吗&#xff1f; 1.大专毕业从事本专业技术工作7年以上&#xff1b;助理满足4年。 2.本科毕业从事本专业技术工作5年以上&#xff0c;助理满足4年。 一般来说中专或者高中学历是无法申请中级职称的&…

mobile代码打APK包

1、安装Android SDK Android SDK 下载地址&#xff1a; http://www.androiddevtools.cn/ 下载位置 下载后解压 打开解压文件&#xff0c;点击 SDK Manager.exe 进行安装 安装组件&#xff0c;这要选 Android 8.0.0 或者以上版本 再次安装&#xff0c;发现没什么可以安装了 2…

【Linux】Shell编程之条件语句

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、条件测试操作作1.文件测试2.整数值比较3.逻辑测试 二、if语句的结构1.单分支结构2.双分支结构3.多分支结构 三、case多分支结构 一、条件测试操作作 test命令 …

Win10蓝屏错误0x0000007b怎么U盘重装系统?

Win10蓝屏错误0x0000007b怎么U盘重装系统&#xff1f;有用户安装好的电脑系统最近总是会出现蓝屏错误0x0000007b的情况&#xff0c;遇到这样的情况很多用户不懂怎么去进行处理。今天分享一个U盘重装系统的方法&#xff0c;教会你快速解决此问题的方法。 准备工作&#xff1a; 1…

体验 nanoGPT

体验 nanoGPT 1. 使用预训练模型2. 训练自己的模型2-1. 准备训练数据2-2. 模型训练2-3. 模型验证 1. 使用预训练模型 在我们尝试训练自己的模型之前&#xff0c;我们先使用其他人训练好的模型&#xff0c;看看如何在自己的环境中运行聊天机器人。 今天我们使用 GPT4ALL 并从 …

正则匹配x.x.x

\d(\.\d){2} 正则规则 \d 表示一个十进制的数字 [0-9] 匹配加号之前的一次或多次 正则中[]、()、{}的区别 [] 匹配组内任意字符 eg&#xff1a;[1,2,3,a-z]能匹配1、2、3、a到z的任意字符 () 相应的匹配字符串&#xff0c;匹配组&#xff0c;子表达式 eg:(abc|cbd)能匹配…

既然有Map了,为什么还要有Redis?

以下内容转自掘金 作者:哪吒编程 同样是缓存&#xff0c;用map不行吗&#xff1f; Redis可以存储几十个G的数据&#xff0c;Map行吗&#xff1f;Redis的缓存可以进行本地持久化&#xff0c;Map行吗&#xff1f;Redis可以作为分布式缓存&#xff0c;Map只能在同一个JVM中进行缓…

2022 Jiangsu Collegiate Programming Contest I. Cutting Suffix

题目链接 Examples input aa Output 1 input ab Output 0 题目大意&#xff1a; 后缀i是字符串从第i个字符开始到最后的字符字串 定义Wi,j是字符串 后缀i和后缀j的公共前缀(LCP)的长度 现在给你一个全集为1-n的互补集T1,T2 要求题目中求和公式的最小值。 题目要点&#xff1a;…

学习笔记(1 - 01)项目初始化的方案和对比

目录 1&#xff0c;创建项目的方式1.1&#xff0c;两种方式创建的项目比对HbuilderX创建的项目&#xff1a;cli创建的项目 1&#xff0c;创建项目的方式 uniapp提供两种方式创建项目&#xff1a; 通过HbuilderX编辑器创建&#xff1a; 通过vue-cli创建 第一方式只能通过Hbuild…

如何在Facebook上创建一个成功的广告账户?

Facebook广告已成为许多企业吸引客户和推广品牌的主要方式。但是&#xff0c;如果你没有经验或知识&#xff0c;创建一个成功的Facebook广告账户可能会变得相当棘手。在这篇文章中&#xff0c;我将向你介绍如何创建一个成功的Facebook广告账户。 第一步&#xff1a;创建Faceboo…

Lucene和Solr和Elasticsearch区别,全文检索引擎工具包Lucene索引流程和搜索流程实操

文章目录 基本概念什么是全文检索技术全文检索的应用场景搜索引擎站内搜索&#xff08;关注&#xff09;文件系统的搜索 Lucene & solr & es介绍区别Solr与Lucene对比ES与Lucene的区别ES与Solr对比 Lucene实现全文检索的流程入门程序需求环境准备数据库脚本初始化Lucen…

ADAS测试方案

一 方案概述 随着5G通讯与互联网的快速发展&#xff0c;智能汽车和ADAS辅助系统的研究与发展在世界范围内也在如火如荼地进行。风丘紧跟时代脚步&#xff0c;经多年积累沉淀&#xff0c;携手整车厂与高校共同研发打造出了一套完整且适用于国内ADAS测试的系统方案。 | ADAS测试…

C/C++每日一练(20230506) 翻转词序、字符金字塔、单词搜索

目录 1. 翻转顺序打印 ※ 2. 字符金字塔 ※ 3. 单词搜索 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 翻转顺序打印 初始化一个字符数组为"Th…

【Java面试八股文】Java基础篇——String+集合+泛型+IO+异常+反射

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线设计模式牛客面试题 目录 三、String 3.1.String常量池 3.2.请你说说String类 3.3.new String("abc")创建了几个字符串对象&#xff1f; 3.4…

双线性插值(Bilinear interpolation)原理推导

文章目录 参考资料前言推导先x方向&#xff0c;后y方向先y方向&#xff0c;后x方向 简化后的双线性插值双线性插值的一阶导 参考资料 https://en.wikipedia.org/wiki/Bilinear_interpolation 前言 双线性插值&#xff0c;又称为双线性内插。在数学上&#xff0c;双线性插值是…

chatGPT的对手,Claude注册教程

完美替代chatGPT&#xff01;Claude注册教程及浅浅的测评 注册 slack 访问地址&#xff1a;https://slack.com/ 点击使用电子邮件注册 建议使用Google邮箱进行登录&#xff0c; 当然使用Google邮箱登录需要使用魔法 登录成功后 创建Slack工作区 我的邀请链接 https://join.…

Ae:绘画工具 - 描边选项

在 Ae 中使用绘画工具&#xff08;画笔工具、仿制图章工具及橡皮擦工具&#xff09;时&#xff0c;都会在时间轴面板的绘画 Paint效果中添加“描边选项” Stroke Options&#xff0c;不同的工具有一些不同的属性。 描边选项里的属性主要用于绘画描边之后的调整&#xff0c;并可…

【Leetcode -405.数字转换为十六进制数 - 409.最长回文串】

Leetcode Leetcode -405.数字转换为十六进制数Leetcode - 409.最长回文串 Leetcode -405.数字转换为十六进制数 题目&#xff1a;给定一个整数&#xff0c;编写一个算法将这个数转换为十六进制数。对于负整数&#xff0c;我们通常使用 补码运算 方法。 注意 : 十六进制中所有…