C++2.0C++复习

C++多线程下的shared_ptr

2018-04-30  本文已影响147人  凉拌姨妈好吃

来看一下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()来判断一个指针是否被释放

上一篇下一篇

猜你喜欢

热点阅读