No, it's not. Line 21 is atomic, but line 38 isn't. An std::shared_ptr can be copied (i.e. have its refcount incremented) atomically, and the copy can be destructed atomically (i.e. decrement its refcount), but it can't be repointed atomically, as that involves changing two datums: the refcount and the pointer.
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.
Now I don't think either line 21 and line 38 are thread safe.
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object
#include <memory>
#include <random>
#include <string>
#include <thread>
#include <iostream>
#include <functional>
#include <cstdlib>
#include <cstring>
void func(std::shared_ptr<std::string> str) {
constauto len = 5;
std::random_device r;
std::default_random_engine el(r());
std::uniform_int_distribution<int> u(1,4);
std::shared_ptr<std::string> array[len];
while (true) {
for (auto &i : array) {
//All member functions (including copy constructor and copy assignment)
//can be called by multiple threads on different instances of shared_ptr
//without additional synchronization even if these instances are copies
//and share ownership of the same object.
int j = u(el);
if (j == 1)
i.reset();
if (j == 2)
i = str;
if (j == 3)
i = std::shared_ptr<std::string>(str);
if (j == 4)
(void*)i.get();
//get() is thread safe, but not for accessing the std::string obj.
//(The variable 'str' and array 'array' can only be access by 'this thread'.)
//(Accessing 'str' or 'array' by multi-thread without additional synchronization
// is not thread safe.)
}
}
}
int main()
{
auto str = std::make_shared<std::string>("I'm a string.");
std::thread a(func, str);
std::thread b(func, str);
func(str);
return 0;
}