std::shared_ptr<int> g_s = std::make_shared<int>(1);
void f1()
{
std::shared_ptr<int>l_s1 = g_s; // read g_s
}
void f2()
{
std::shared_ptr<int> l_s2 = std::make_shared<int>(3);
std::thread th(f1);
th.detach();
g_s = l_s2; // write g_s
}
Regarding the code above, I know different threads reading and writing the same shared_ptr
leads to race conditions. But how about weak_ptr
? Is there any race condition in the code below? (My platform is Microsoft VS2013.)
std::weak_ptr<int> g_w;
void f3()
{
std::shared_ptr<int>l_s3 = g_w.lock(); //2. here will read g_w
if (l_s3)
{
;/.....
}
}
void f4()
{
std::shared_ptr<int> p_s = std::make_shared<int>(1);
g_w = p_s;
std::thread th(f3);
th.detach();
// 1. p_s destory will motify g_w (write g_w)
}
For brevity in the following discussion, different
weak_ptr
s andshared_ptr
s that all are generated from the same originalshared_ptr
orunique_ptr
will be termed 'instances'.weak_ptr
s andshared_ptr
s that don't share the same object do not need to be considered in this analysis. The general rules for assessing thread safety are:const
member function calls on the same instance are thread-safe. All observer functions areconst
.The following table shows thread-safety when two threads are operating on the same instance at the same time.
The cppreference discussion of std::atomic(std::weak_ptr) is clearest on the safety of simultaneous accesses to different instances:
C++20 introduces a
std::atomic
specialization of weak pointer that provides thread-safe modification of the same instance through appropriate synchronization. Note that when it comes to constructors, initialization from another instance is not atomic. For example,atomic<weak_ptr<T>> myptr(anotherWeakPtr);
is not an atomic operation.shared_ptr
andweak_ptr
fall under the same blanket threadsafety requirements as all other standard library types: simultaneous calls to member functions must be threadsafe if those member functions are non-modifying (const
) (Detailed in C++11 §17.6.5.9 Data Race Avoidance [res.data.races]). Assignment operators are notably notconst
.I know I'm late, but this comes up when searching for "weak_ptr thread", and Casey's answer just isn't the whole truth. Both
shared_ptr
andweak_ptr
can be used from threads without further synchronization.For
shared_ptr
, there's a lot of documentation (e.g. on cppreference.com or on stackoverflow). You can safely accessshared_ptr
's that point to the same object from different threads. You just can't bang on the same pointer from two threads. In other words:To solve that problem in your code, pass
g_s
as parameter (by value)* tof1()
.For weak pointers, the safety guarantee is hidden in the documentation for weak_ptr::lock:
You can use
weak_ptr::lock()
to get ashared_ptr
from other threads without further synchronization. This is also confirmed here for Boost and in this SO answer by Chris Jester-Young.Again, you have to make sure not to modify the same
weak_ptr
from one thread while accessing it from another, so passg_w
intof3()
by value as well.