多线程读写shared_ptrshared_ptr要加锁分析!学习笔记
(shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,“因为 shared_ptr 有两个数据成员,读写操作不能原子化"。使得多线程读写同一个 shared_ptr 对象需要加锁
• 一个 shared_ptr 对象实体可被多个线程同时读取;
• 两个 shared_ptr 对象实体可以被两个线程同时写入,“析构”算写操作;
• 如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁。
================================================================================
请注意,以上是 shared_ptr 对象本身的线程安全级别,不是它管理的对象的线程安全级别。
总结:书本上的一句话就是 不要对标准库抱有线程安全的幻想!!!!!!!!!需要各种分析到底安全与否!!!
shared_ptr 的数据结构:!!!!!
shared_ptr 是引用计数型(reference counting)智能指针,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法(除此之外理论上还有用循环链表的办法,不过没有实例)。具体来说,shared_ptr<Foo> 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针(其类型不一定是原始指针,有可能是 class 类型,但不影响这里的讨论),指向堆上的 ref_count 对象。ref_count 对象有多个成员,具体的数据结构如图 1 所示,其中 deleter 和 allocator 是可选的。
为了简化并突出重点,后文只画出 use_count:
以上是 shared_ptr<Foo> x(new Foo); 对应的内存数据结构。
如果再执行 shared_ptr<Foo> y = x; 那么对应的数据结构如下。
但是 y=x 涉及两个成员的复制,这两步拷贝不会同时(原子)发生。
中间步骤 1,复制 ptr 指针:
中间步骤 2,复制 ref_count 指针,导致引用计数加 1:
步骤1和步骤2的先后顺序跟实现相关(因此步骤 2 里没有画出 y.ptr 的指向),我见过的都是先1后2。
既然 y=x 有两个步骤,如果没有 mutex 保护,那么在多线程里就有 race condition即资源竞争。
多线程无保护读写 shared_ptr 可能出现的 race condition:!!!!!!!!!!
考虑一个简单的场景,有 3 个 shared_ptr<Foo> 对象 x、g、n:
- 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 线程。
同时编程 B 执行 g = n; (即 write G),两个步骤一起完成了。
先是步骤 1:
再是步骤 2:
这是 Foo1 对象已经销毁,x.ptr 成了空悬指针!
最后回到线程 A,完成步骤 2:
多线程无保护地读写 g,造成了“x 是空悬指针”的后果。这正是多线程读写同一个 shared_ptr 必须加锁的原因。
当然,race condition 远不止这一种,其他线程交织(interweaving)有可能会造成其他错误。
思考,假如 shared_ptr 的 operator= 实现是先复制 ref_count(步骤 2)再复制 ptr(步骤 1),会有哪些 race condition?
多线程读写shared_ptrshared_ptr要加锁分析!学习笔记的更多相关文章
- 为什么多线程读写 shared_ptr 要加锁?
https://www.cnblogs.com/Solstice/archive/2013/01/28/2879366.html 为什么多线程读写 shared_ptr 要加锁? 陈硕(giantch ...
- ELK日志分析 学习笔记
(贴一篇之前工作期间整理的elk学习笔记) ELK官网 https://www.elastic.co ELK日志分析系统 学习笔记 概念:ELK = elasticsearch + logstas ...
- 基于FP-Growth算法的关联性分析——学习笔记
数据挖掘 比之前的Ap快,因为只遍历两次. 降序 一.构建FP树 对频繁项集排序,以构成共用关系. 二.基于FP树的频繁项分析 看那个模式基出现过几次.频繁度. 看洗发液的 去掉频繁度小的 构建洗发液 ...
- 读写分离&分库分表学习笔记
读写分离 何为读写分离? 见名思意,根据读写分离的名字,我们就可以知道:读写分离主要是为了将对数据库的读写操作分散到不同的数据库节点上. 这样的话,就能够小幅提升写性能,大幅提升读性能. 我简单画了一 ...
- 在多线程中进行UI操作--ios学习笔记
iOS 上不建议在非主线程进行UI操作,在非主线程进行UI操作有很大几率会导致程序崩溃,或者出现预期之外的效果. 我开始不知道这一点,在子线程中进行了弹窗操作,结果程序就出问题了! 报的错误是(EXC ...
- java.util.BitSet 详细分析 学习笔记
1,BitSet类 大小可动态改变, 取值为true或false的位集合.用于表示一组布尔标志. 此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的 ...
- java多线程——竞态条件与临界区 学习笔记
允许被多个线程同时执行的代码称作线程安全的代码.线程安全的代码不包含竞态条件.当多个线程同时更新共享资源时会引发竞态条件.因此,了解 Java 线程执行时共享了什么资源很重要. 一.局部变量(函数内定 ...
- C# IO流与文件读写学习笔记
本笔记摘抄自:https://www.cnblogs.com/liyangLife/p/4797583.html,记录一下学习过程以备后续查用. 一.文件系统 1.1文件系统类的介绍 文件操作类大都在 ...
- Python学习笔记进阶篇——总览
Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(Socket编程进阶&多线程.多进程) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(异常处理) Pyth ...
随机推荐
- 数字图像处理实验(2):PROJECT 02-02, Reducing the Number of Gray Levels in an Image 标签: 图像处理MATLAB 2017-
实验要求: Reducing the Number of Gray Levels in an Image Objective To understand how the number of gray ...
- ZROI2018提高day5t3
传送门 分析我们可以根据性质将这个序列构造成一个环:0,a[1~n],0,a[n~1] 这中间的0是为了起间隔作用的. 我们又知道b[i]=a[i-1]^a[i+1] c[i]=b[i-1]^b[i+ ...
- Linux-shell实现阳历转农历(序)
好些天没有登陆邮箱,前几天上班打开一看垃圾箱中有一封邮件让我好激动,还是国外友人的英文邮件.^_^大概内容是我早些时候写的一个阳历转农历的shell小程序,他在用的时候发现了bug,但是这个bug我在 ...
- Java Swing 创建转圈的进度提示框
Java Swing 创建转圈的进度提示框 摘自 https://blog.csdn.net/nihaoqiulinhe/article/details/52439486 置顶2016年09月05日 ...
- Python程序设计9——数据库编程
1 数据持久化 持久化是将内存中的对象存储在关系数据库中,当然也可以存储在磁盘文件.XML数据文件中.实现数据持久化至少需要实现以下3个接口 void Save(object o):把一个对象保存到外 ...
- mybatis spring maven
maven版本:3.3.9 解压即可使用 spring版本:4.3.9 通过maven进行管理下载 mybatis版本:3.4.4 通过maven进行管理下载 mysql版本:5.7 conne ...
- HTTP 协议 -- 状态码
HTTP 协议状态码(Http Status Code) 使用ASP.NET/PHP/JSP 或者javascript都会用到http的不同状态,一些常见的状态码为: 200 – 服务器成功返回网页 ...
- 动态合并或定制GridView控件Header头某些列
开发时,有时会对GridView控件头做一些字段合并.多行表头,多列合并,明白了其中的原理,实现起来,均能运用自如.下面Insus.NET分享自己的做法. 创建站点,创建aspx网页,拉GridVie ...
- Gazebo学习随记2 SDF和XML
Model 模型 一个模型数据库会拥有的文件 database.config:有关数据库的元数据,从CMakeList自动填充『本地不需要』 model文件夹 一个模型[奏是辣个文件夹]会有的文件 m ...
- 教学ppt设计与制作
分三部分陈述,分别是元素呈现/版面设计/导航设计/. 1 元素呈现 文本 (1)字符表现策略 少用宋体 多用黑体,微软雅黑等 少用艺术字 (2)段落表现策略 条目化 一行一条 用符号简化文字描述 按有 ...