shared_ptr 智能指针 详解
2015-10-09 11:41
148 查看
感觉网上的内容讲解的都不是太说到点子上,陈硕说的还是非常好的。
shared_ptr: 引用计数智能指针。 与
(有的人可能会想要采用 static 来实现引用计数,这是不对的)。
一个shared_ptr对象可以被多个线程同时读取
两个 shared_ptr 对象可以被 两个线程同时写入,”析构函数“ 算是写操作。
如果两个 线程需要同时写一个 “shared_ptr”对象,那么需要加锁操作。
请注意,以上是shared_ptr对象本身的线程安全级别,不是它所管理的对象的线程安全级别
以上内容摘自陈硕的博客,讲的很清楚,不过需要时间理解。
两个线程对同一个shared_ptr对象读肯定是线程安全的。
两个
如果同一个
我的理解是: 因为 shared_ptr 需要保证 “两个shared_ptr对象可以被两个线程同时写入,析构算是写操作,哪怕这两个shared_ptr 管理同一个对象“ 这个线程安全的级别。
具体来说:
sp1 与 sp2 中都有两个指针,并且指向的地方相同。 指向 new int(3) 这片空间, 指向 引用计数的区间。 当线程1 中的 sp1 析构的时候,引用计数此时会减一,这个时候必须是原子操作,才可以保证正确性。 因为需要达到这个级别的线程安全,所以 引用计
数必须是原子类型的。
[2] 分析与实现/article/5603650.html
[3] http://en.cppreference.com/w/cpp/memory/shared_ptr
[4] shared_ptr 线程安全分析 /article/9649198.html
[5] 源码剖析 /article/3461991.html
[6] quora https://cppwisdom.quora.com/shared_ptr-is-almost-thread-safe
[7] stackoverflow http://stackoverflow.com/questions/9127816/stdshared-ptr-thread-safety-explained
[8] stackoverflow http://stackoverflow.com/questions/14482830/stdshared-ptr-thread-safety
shared_ptr: 引用计数智能指针。 与
auto_ptr的区别是,
shared_ptr实现时包含一个引用计数(count-ref)。在一个
shared_ptr对象销毁的时候,会将引用计数减一,直到引用计数为0的时候才真正的会销毁其所指向的对象。
int main(){ shared_ptr<int> sp1(new int(3)); shared_ptr<int> sp2; sp2 = sp1; //引用计数会增加1,不会导致所有权的转移。 return 0; //在函数结束的时候会调用这些局部变量的析构函数,会将引用计数减一,直到引用计数为0. }
shared_ptr 的内部实现
包括两个部分: T*m_data指向真正的对象; 引用计数的指针(堆上的内存空间的分配)。(有的人可能会想要采用 static 来实现引用计数,这是不对的)。
VS中 shared_ptr的实现方式,如下图所示:
shared_ptr 线程安全
根据Boost的标准库文档,shared_ptr的线程安全级别 与内建模型,标准库容器、std::string一样,即:
一个shared_ptr对象可以被多个线程同时读取
两个 shared_ptr 对象可以被 两个线程同时写入,”析构函数“ 算是写操作。
如果两个 线程需要同时写一个 “shared_ptr”对象,那么需要加锁操作。
请注意,以上是shared_ptr对象本身的线程安全级别,不是它所管理的对象的线程安全级别
以上内容摘自陈硕的博客,讲的很清楚,不过需要时间理解。
两个线程对同一个shared_ptr对象读肯定是线程安全的。
两个
shared_ptr对象管理同一个对象,并且分别被两个线程操作: 如果只是操作
shared_ptr对象本身,比如说 给这个对象赋值、调用其析构函数、作为复制构造函数的参数等,那么是线程安全的(因为只会操作引用计数,而引用计数是无锁且安全的)。如果两个线程是同时操作
shared_ptr所指向的对象,那么是线程不安全的。 因为对其所管理的对象是没有加锁的。
如果同一个
shared_ptr对象 被两个线程同时访问(写),不是线程安全的。 因为
shared_ptr对象包括两个部分
引用计数 与 数据指针。 对这个两个部分的同时访问不是原子操作得。 所以一定不是线程安全得。
shared_ptr对象的引用计数是无锁其安全的,如何实现无锁且安全的呢? 因为引用计数只是一个
integer 变量所以可以用
原子变量来实现。(特殊的机器指令)
shared_ptr 使用技巧
shared_ptr 的 引用计数含有指向 class T的指针的原因?
引用计数是原子类型的原因?
对于 “为什么引用计数需要原子操作?” 的答案。我的理解是: 因为 shared_ptr 需要保证 “两个shared_ptr对象可以被两个线程同时写入,析构算是写操作,哪怕这两个shared_ptr 管理同一个对象“ 这个线程安全的级别。
具体来说:
shared_ptr<int> sp1(new int(3)); //线程1,执行 shared_ptr<int> sp2 = sp1; //线程2,执行。
sp1 与 sp2 中都有两个指针,并且指向的地方相同。 指向 new int(3) 这片空间, 指向 引用计数的区间。 当线程1 中的 sp1 析构的时候,引用计数此时会减一,这个时候必须是原子操作,才可以保证正确性。 因为需要达到这个级别的线程安全,所以 引用计
数必须是原子类型的。
参考
[1] 陈硕 http://www.cppblog.com/Solstice/archive/2013/01/28/197597.html[2] 分析与实现/article/5603650.html
[3] http://en.cppreference.com/w/cpp/memory/shared_ptr
[4] shared_ptr 线程安全分析 /article/9649198.html
[5] 源码剖析 /article/3461991.html
[6] quora https://cppwisdom.quora.com/shared_ptr-is-almost-thread-safe
[7] stackoverflow http://stackoverflow.com/questions/9127816/stdshared-ptr-thread-safety-explained
[8] stackoverflow http://stackoverflow.com/questions/14482830/stdshared-ptr-thread-safety
相关文章推荐
- Android每日范例——文字超链接
- 你必须了解的Session的本质
- 【学习笔记】系列八:Web性能压力测试工具之ApacheBench(ab)详解
- VIM常用快捷键
- Spark1.5.1 编译与安装
- B/S结构-登录页面-测试用例设计
- URAL 1146 Maximum Sum (最大子矩阵)
- 重力碰撞
- Java Map遍历速度最优解
- jQuery+PHP实现可编辑表格字段内容并实时保存
- VS2013 VC2013 VC 远程调试 配置步骤
- 【OCJP】 第1题---允许使用泛型类,避免一个不用检查的警告
- elasticsearch 启动
- 压缩文件为zip包导致的中文名称的文件变成乱码
- html 美化滚动条默认样式
- 1013. Battle Over Cities (25)
- 狮子不会在乎绵羊的评价
- 重力动画
- Xcode中添加.pch文件
- Linux下查看进程的执行文件绝对路径