shared_ptr之多线程
2015-09-15 18:57
351 查看
shared_ptr的实现
看了一下stl的源码,shared_ptr的实现是这样的: shared_ptr模板类有一个__shared_count类型的成员_M_refcount来处理引用计数的问题。__shared_count也是一个模板类,它的内部有一个指向Sp_counted_base_impl类型的指针_M_pi。所有引用同一个对象的shared_ptr都共用一个_M_pi指针。当一个shared_ptr拷贝复制时, _M_pi指针调用_M_add_ref_copy()函数将引用计数+1。 当shared_ptr析构时,_M_pi指针调用_M_release()函数将引用计数-1。 _M_release()函数中会判断引用计数是否为0. 如果引用计数为0, 则将shared_ptr引用的对象内存释放掉。
?
?
。例如: 有两个shared_ptr p1和p2, 运行p1= p2 。 假如p1和p2是引用同一个对象的,那么引用计数不变。 如果p1和p2是指向不同对象的,那么p1所指向对象的引用计数-1, p2指向对象的引用计数+1。
?
_M_dispose函数会将share_ptr引用的对象释放内存。
?
下面是我写的一段简单的测试代码:
?
shared_ptr.h 169行是__shared_count拷贝构造时增加引用计数,184行是__shared_count赋值操作,161行是__share_count的析构时减少引用计数, 79行是释放引用对象的内存。
?
shared_ptr线程安全性问题
关于shared_ptr的线程安全性。查了一些网上的资料,有的说是安全的,有的说不安全。引用CSDN上一篇比较老的帖子,它是这样说的:
“Boost 文档对于 shared_ptr 的线程安全有一段专门的记述,内容如下:
shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)
Any other simultaneous accesses result in undefined behavior.
翻译为中文如下:
shared_ptr 对象提供与内建类型一样的线程安全级别。一个 shared_ptr 实例可以同时被多个线程“读”(仅使用不变操作进行访问)。 不同的 shared_ptr 实例可以同时被多个线程“写入”(使用类似 operator= 或 reset 这样的可变操作进行访问)(即使这些实 例是拷贝,而且共享下层的引用计数)。
任何其它的同时访问的结果会导致未定义行为。”
这几句话比较繁琐,我总结一下它的意思:
1 同一个shared_ptr被多个线程“读”是安全的。
2 同一个shared_ptr被多个线程“写”是不安全的。
3 共享引用计数的不同的shared_ptr被多个线程”写“ 是安全的。
如何印证上面的观点呢?
其实第一点我觉得比较多余。因为在多个线程中读同一个对象,在正常情况下不会有什么问题。
所以问题就是:如何写程序证明同一个shared_ptr被多个线程"写"是不安全的?
我的思路是,在多个线程中同时对一个shared_ptr循环执行两遍swap。 shared_ptr的swap函数的作用就是和另外一个shared_ptr交换引用对象和引用计数,是写操作。执行两遍swap之后, shared_ptr引用的对象的值应该不变。
程序如下:
?
程序运行的结果如下:
?
它不是直接对全局变量gp进行写操作,而是将gp拷贝出来一份再进行写操作。运行的结果如下:
?
补充一个问题: 为什么shared_ptr可以作为STL标准容器的元素,而auto_ptr不可以
这篇文章小结一下:
1 shared_ptr是一个非常实用的智能指针。
2 shared_ptr的实现机制是在拷贝构造时使用同一份引用计数。
3 对同一个shared_ptr的写操作不是线程安全的。 对使用同一份引用计数的不同shared_ptr是线程安全的。
相关文章推荐
- idea在WEB-INF下建立lib目录导入jar包
- 兔子--ButterKnife的使用
- hdu3072 强连通+最小树形图
- rails网站分享到朋友圈功能是怎么实现的
- 使用Uncrustify在Xcode中格式化Objective-C代码
- SpringMvc[学习手记]-框架搭建
- 学习笔记--进程及线程间通信方式的区别及联系
- QQ中未读气泡拖拽消失的实现分析
- android应用使用ant打包过程
- Android开发入门(初学)
- linux 查找文件或目录
- Java中堆内存与栈内存分配浅析
- Qt 学习之路:输入元素
- 判断iOS设备型号
- string object to oracle check
- Python学习笔记 -- 第一章
- Redis的图形界面管理工具phpRedisAdmin
- IDisposable接口
- Android的Handler总结
- 14级组队赛第一场3319 A simple water problem