std::shared_ptr thread safety explained

杀马特。学长 韩版系。学妹 提交于 2019-12-17 05:38:18

问题


I'm reading http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html and some thread safety issues are still not clear for me:

  1. Standard guarantees that reference counting is handled thread safe and it's platform independent, right?
  2. Similar issue - standard guarantees that only one thread (holding last reference) will call delete on shared object, right?
  3. shared_ptr does not guarantee any thread safety for object stored in it?

EDIT:

Pseudo code:

// Thread I
shared_ptr<A> a (new A (1));

// Thread II
shared_ptr<A> b (a);

// Thread III
shared_ptr<A> c (a);

// Thread IV
shared_ptr<A> d (a);

d.reset (new A (10));

Calling reset() in thread IV will delete previous instance of A class created in first thread and replace it with new instance? Moreover after calling reset() in IV thread other threads will see only newly created object?


回答1:


As others have pointed out, you've got it figured out correctly regarding your original 3 questions.

But the ending part of your edit

Calling reset() in thread IV will delete previous instance of A class created in first thread and replace it with new instance? Moreover after calling reset() in IV thread other threads will see only newly created object?

is incorrect. Only d will point to the new A(10), and a, b, and c will continue to point to the original A(1). This can be seen clearly in the following short example.

#include <memory>
#include <iostream>
using namespace std;

struct A
{
  int a;
  A(int a) : a(a) {}
};

int main(int argc, char **argv)
{
  shared_ptr<A> a(new A(1));
  shared_ptr<A> b(a), c(a), d(a);

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  d.reset(new A(10));

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  return 0;                                                                                                          
}

(Clearly, I didn't bother with any threading: that doesn't factor into the shared_ptr::reset() behavior.)

The output of this code is

a: 1 b: 1 c: 1 d: 1

a: 1 b: 1 c: 1 d: 10




回答2:


  1. Correct, shared_ptrs use atomic increments/decrements of a reference count value.

  2. The standard guarantees only one thread will call the delete operator on a shared object. I am not sure if it specifically specifies the last thread that deletes its copy of the shared pointer will be the one that calls delete (likely in practice this would be the case).

  3. No they do not, the object stored in it can be simultaneously edited by multiple threads.

EDIT: Slight followup, if you want to get an idea of how shared pointers work in general you might want to look at the boost::shared_ptr source: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp.




回答3:


std::shared_ptr is not thread safe.

A shared pointer is a pair of two pointers, one to the object and one to a control block (holding the ref counter, links to weak pointers ...).

There can be multiple std::shared_ptr and whenever they access the control block to change the reference counter it's thread-safe but the std::shared_ptr itself is NOT thread-safe or atomic.

If you assign a new object to a std::shared_ptr while another thread uses it, it might end up with the new object pointer but still using a pointer to the control block of the old object => CRASH.



来源:https://stackoverflow.com/questions/9127816/stdshared-ptr-thread-safety-explained

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!