std::shared_ptr thread safety explained

Goofy picture Goofy · Feb 3, 2012 · Viewed 64.5k times · Source

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?

Answer

Nicu Stiurca picture Nicu Stiurca · Nov 30, 2012

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