1.9 再论shared_ptr 的线程安全

虽然我们借shared_ptr 来实现线程安全的对象释放,但是shared_ptr 本身不是100% 线程安全的。它的引用计数本身是安全且无锁的,但对象的读写则不是,因为shared_ptr 有两个数据成员,读写操作不能原子化。根据文档11,shared_ptr 的线程安全级别和内建类型、标准库容器、std::string 一样,即:

一个shared_ptr 对象实体可被多个线程同时读取;

两个shared_ptr 对象实体可以被两个线程同时写入,“析构”算写操作;

如果要从多个线程读写同一个shared_ptr 对象,那么需要加锁。

请注意,以上是shared_ptr 对象本身的线程安全级别,不是它管理的对象的线程安全级别。

要在多个线程中同时访问同一个shared_ptr,正确的做法是用mutex 保护:

  1. MutexLock mutex; // No need for ReaderWriterLock
  2. shared_ptr<Foo> globalPtr;
  3. // 我们的任务是把globalPtr 安全地传给doit()
  4. void doit(const shared_ptr<Foo>& pFoo);

globalPtr 能被多个线程看到,那么它的读写需要加锁。注意我们不必用读写锁,而只用最简单的互斥锁,这是为了性能考虑。因为临界区非常小,用互斥锁也不会阻塞并发读。

为了拷贝globalPtr,需要在读取它的时候加锁,即:

  1. void read()
  2. {
  3. shared_ptr<Foo> localPtr;
  4. {
  5. MutexLockGuard lock(mutex);
  6. localPtr = globalPtr; // read globalPtr
  7. }
  8. // use localPtr since here,读写localPtr 也无须加锁
  9. doit(localPtr);
  10. }

写入的时候也要加锁:

  1. void write()
  2. {
  3. shared_ptr<Foo> newPtr(new Foo); // 注意,对象的创建在临界区之外
  4. {
  5. MutexLockGuard lock(mutex);
  6. globalPtr = newPtr; // write to globalPtr
  7. }
  8. // use newPtr since here,读写newPtr 无须加锁
  9. doit(newPtr);
  10. }

注意到上面的read() 和write() 在临界区之外都没有再访问globalPtr,而是用了一个指向同一Foo 对象的栈上shared_ptr local copy。下面会谈到,只要有这样的local copy 存在,shared_ptr 作为函数参数传递时不必复制,用reference to const 作为参数类型即可。另外注意到上面的new Foo 是在临界区之外执行的,这种写法通常比在临界区内写globalPtr.reset(new Foo) 要好,因为缩短了临界区长度。如果要销毁对象,我们固然可以在临界区内执行globalPtr.reset(),但是这样往往会让对象析构发生在临界区以内,增加了临界区的长度。一种改进办法是像上面一样定义一个localPtr,用它在临界区内与globalPtr 交换(swap()),这样能保证把对象的销毁推迟到临界区之外。练习:在write() 函数中,globalPtr = newPtr; 这一句有可能会在临界区内销毁原来globalPtr 指向的Foo 对象,设法将销毁行为移出临界区。

为什么多线程读写 shared_ptr 要加锁?

shared_ptr线程安全性分析

shared_ptr的线程安全的更多相关文章

  1. shared_ptr的线程安全性

    一: All member functions (including copy constructor and copy assignment) can be called by multiple t ...

  2. shared_ptr智能指针源码剖析

    (shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化.根据文档 (http://www.boost.org/doc/ ...

  3. 为什么多线程读写 shared_ptr 要加锁?

    https://www.cnblogs.com/Solstice/archive/2013/01/28/2879366.html 为什么多线程读写 shared_ptr 要加锁? 陈硕(giantch ...

  4. C++之shared_ptr总结

    转自 http://blog.csdn.net/u013696062/article/details/39665247 Share_ptr也是一种智能指针.类比于auto_ptr学习.所以推荐先学习a ...

  5. shared_ptr 和auto_ptr智能指针

    shared_ptr:计数的智能指针 它是一个包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时 ...

  6. shared_ptr 用法

    引入 shared_ptr 是c++为了提高安全性而添加的智能指针,方便了内存管理. 特点 shared_ptr 是通过指针保持对象共享所有权的智能指针.多个 shared_ptr 对象可占有同一对象 ...

  7. 深入理解智能指针之shared_ptr(一)

    本文基于C++标准库源码分析shared_ptr,旨在搞清楚shared_ptr是什么,线程安全性等,目标能够安全的使用智能指针. (一)shared_ptr是一个类. 首先可以确定的是shared_ ...

  8. C++11智能指针

    今晚跟同学谈了一下智能指针,突然想要看一下C++11的智能指针的实现,因此下了这篇博文. 以下代码出自于VS2012 <memory> template<class _Ty> ...

  9. Boost使用笔记(Smart_ptr)

    我是Word写的,复制过来实在懒得在排版了,有兴趣的朋友可以去我的百度文库看,谢谢 http://wenku.baidu.com/view/34e485e2f61fb7360b4c653e.html ...

随机推荐

  1. 故如果要比较两个字符串是否相同可以对a调用equal

    故如果要比较两个字符串是否相同(而不是他们的地址是否相同).可以对a调用equal: System.out.println(a.equal(b)); equal用来比较两个对象中字符串的顺序. a.e ...

  2. 透過 bc 計算 pi

    echo "scale=${num}; 4*a(1)" | bc -lq例如: echo "scale=5000; 4*a(1)" | bc -lq 4*a(1 ...

  3. [css]解决iframe在ios设备上无法滚动

    原因: safari的webkit内核特性 解决方案: 在iframe外包裹一层div并另外设置其css属性为如下: -webkit-overflow-scrolling:touch; overflo ...

  4. 20 个常用的 CSS 技巧

    1. 黑白图像 这段代码会让你的彩色照片显示为黑白照片,是不是很酷? img.desaturate {    filter: grayscale(100%);    -webkit-filter: g ...

  5. windows 系统重装之后怎么恢复oracle数据库

    今天单位的服务器系统进不去了,重做了系统,有重要的oracle数据,经理让我恢复一下oracle数据,试着尝试了一下 1.首先,将原来的ORACLE文件夹改名,原来的路径是D:/oracle.我暂时改 ...

  6. Hibernate_day04--课程安排_Hibernate查询方式_对象导航查询_OID查询

    Hibernate_day04 上节内容 今天内容 Hibernate查询方式 对象导航查询 OID查询 HQL查询 查询所有 条件查询 排序查询 分页查询 投影查询 聚集函数使用 QBC查询 查询所 ...

  7. NUC972 MDK NON-OS

     NUC972直接可以在BSP包里模板进行编程,烧录用Nu writer  http://www2.keil.com/mdk5/legacy 下载对应的安装包的插件 是直接下载到DDR 里面去运行,所 ...

  8. poj_2486 动态规划

    题目大意 N个节点构成一棵树,每个节点上有一个权重val[i], 从根节点root出发在树上行走,行走的时候只能沿着树枝行进.最多在树上走k步,每第一次到达某个节点j,可以获得val[j]的收益,求从 ...

  9. [黑金原创教程] FPGA那些事儿《设计篇 II》- 图像处理前夕·续

    简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...

  10. 简介Objective-C语言

    2011-05-11 11:20 佚名 百度百科 字号:T | T Objective-C,是扩充C的面向对象编程语言.主要使用于Mac OS X和GNUstep这两个使用OpenStep标准的系统, ...