Search code examples
c++c++11thread-safetyshared-ptrsmart-pointers

To what degree does std::shared_ptr ensure thread-safety?


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?


Solution

  • 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