C++多线程下的shared_ptr

来看一下boost文档下给出的shared_ptr的多线程读写的例子

shared_ptr<int> p(new int(42));

//一个shared_ptr实体允许被多个线程读取
// thread A
shared_ptr<int> p2(p); // reads p
// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe

//一个shared_ptr实体不允许被多个线程同时读写
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

shared_ptr引用计数是原子的,它的析构函数原子地将引用计数减去1,当多个线程对同一对象析构时,也只会出现执行顺序的交错,不会有内存泄露。
那么同理shared_ptr的构造函数赋值析构都是线程安全的。

何时不安全呢?就是在我们通过shared_ptr.get()和*解引用获得了指向该内存的原始指针,那么后面都是对原始指针的操作,所以我们需要自己控制线程的安全。(如shared_ptr.rest 和 swap)

通俗来讲,当我们同时读写同一个对象的时候,无法确保编译器是先操作引用计数还是先操作指针,在这个时候就需要加锁,避免出现空悬指针

那么如何使多个线程可以对同一个shared_ptr实体进行同时读写?

运用weak_ptr这个助手检测指针是否被释放
没使用前:

class tester 
{
public:
  tester() {}
  ~tester() {}
public:
  boost::shared_ptr<int> m_spData; // 可能其它类型。
};

tester gObject;

void fun(void)
{
  // !!!在这大量使用sp指针.
  boost::shared_ptr<int> tmp = gObject.m_spData;
}

int main()
{
  // 多线程。
  boost::thread t1(&fun);
  boost::thread t2(&fun);
  t1.join();
  t2.join();
  return 0;
}

改进后:

class tester 
{
public:
  tester() {}
  ~tester() {}
  // 更多的函数定义…
};

void fun(boost::weak_ptr<tester> wp)
{
  boost::shared_ptr<tester> sp = wp.lock;
  if (sp)
  {
    // 在这里可以安全的使用sp指针.
  }
  else
  {
    std::cout << “指针已被释放!” << std::endl;
  }
} 

int main()
{
  boost::shared_ptr<tester> sp1(new tester);
  boost.weak_ptr<tester> wp(sp1);
  // 开启两个线程,并将智能指针传入使用。
  boost::thread t1(boost::bind(&fun, wp));
  boost::thread t2(boost::bind(&fun, wp));
  t1.join();
  t2.join();
  return 0;
}

使用weak_ptr.lock函数就可以得到一个shared_ptr的指针,如果该指针已经被其它地方释放,它则返回一个空的shared_ptr,也可以使用weak_ptr.expired()来判断一个指针是否被释放

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 13,146评论 1 51
  • 本文版权归 liancheng 所有,如有转载请按如下方式标明原创作者及出处,以示尊重!!原创作者:lianche...
    周肃阅读 12,265评论 2 6
  • 1. C++基础知识点 1.1 有符号类型和无符号类型 当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值...
    Mr希灵阅读 18,065评论 3 82
  • 原作者:Babu_Abdulsalam 本文翻译自CodeProject,转载请注明出处。 引入### Ooops...
    卡巴拉的树阅读 30,254评论 13 74
  • 因为狗年,我特别记起我们家养过的一条狗。 那是一条极普通的狗,普通到我想不起它有什么特别之处。只因为它是我们家养过...
    Lin太阳阅读 2,662评论 2 2