std::shared_ptr<Dog> pd;
void F() {
pd = std::make_shared<Dog>("Smokey");
}
int main() {
std::thread t1(F);
std::thread t2(F);
t1.join();
t2.join();
return 0;
}
std::shared_ptr<Dog> pd(new Dog("Gunner"));
void F() {
std::shared_ptr<Dog> localCopy = pd;
}
int main() {
std::thread t1(F);
std::thread t2(F);
t1.join();
t2.join();
return 0;
}
In C++, I understand that std::shared_ptr is thread-safe for reading and copying. But I'm a little confused about when I need to use a mutex to synchronize threads. I have two code snippets. In the first one, std::shared_ptr is being modified by multiple threads. In the second one, each thread is only reading from and copying the shared pointer. Do I need a mutex in both situations, or just in the first one? Why or why not?"
It's easier to understand this if you carefully identify all the moving pieces involved:
a reference-counted object, this is an object, somewhere, this is your Dog
the reference counter itself, this keeps track of the number of references to the reference-counted object
the shared pointer itself, that uses the reference counter
These are all, discrete entities, that need to be considered, and evaluated, separately.
As a rule of thumb, in C++ if an object is accessed from multiple execution threads, and at least one execution thread "modifies" it, in some way, then the execution threads must be "synchronized" with respect to this object; unless the object is "thread-safe". What does "synchronize" mean? Well, it means more than just a mutex, somewhere; but for this practical example this is what it means: you need to access the object while holding a lock on some mutex, somewhere.
Data point: the reference counter is thread-safe. The smart pointer, a.k.a std::shared_ptr
is not.
pd = std::make_shared<Dog>("Smokey");
This modifies the shared pointer, pd
, in multiple execution threads. This requires synchronization, this is not thread safe. You need a mutex.
std::shared_ptr<Dog> localCopy = pd;
This makes a copy of pd
, it does not modify it. This also juggles the reference counter, as part of making a copy (and destroying) it. The reference-counter is thread safe. The shared pointer is not being modified, only accessed. This is thread safe.