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?
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_ptr
s 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.