Search code examples
c++11thread-safetyshared-ptr

Is thread safe to assign a shared_ptr nullptr?


Suppose there is a shared_ptr:

std::shared_ptr<MyClass> myPtr = std::make_shared(new MyClass());

In worker thread:

myPtr = nullptr;

In main thread:

if( myPtr != nullptr )
{
    // do something
}

Is the code above thread safe? Or can the main thread see the new value immediately?


Solution

  • No, this is not thread-safe.

    A shared_ptr behaves like a built-in type regarding thread-safety: Concurrent access to distinct objects is fine, while concurrent access to the same object is not. That is, multiple threads may manipulate different shared_ptrs pointing to the same object as they like. But as soon as you share the shared_ptr itself, things get dangerous.

    Use the atomic non-member functions to access the same shared_ptr object concurrently from multiple threads:

    // atomically set myPtr to nullptr
    std::atomic_store(&myPtr, std::shared_ptr<MyClass>{});
    [...]
    
    
    // atomically check the current value of myPtr
    if(std::atomic_load(&myPtr) != nullptr) [...]
    

    Note that this only works if all threads accessing the shared_ptr only do so through the atomic functions. Otherwise you might still end up with a data race. To make this restriction more explicit in the source code, C++20 introduced specializations for std::atomic<std::shared_ptr> and deprecated the old free functions.