关于使用 shared_ptr 的线程安全问题
Question about the thread-safety of using shared_ptr
众所周知,shared_ptr
仅保证对底层控制块的访问是线程
安全且不保证访问拥有的对象。
那为什么there is a race condition in the code snippet below:
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
}
在上面的代码片段中,确实没有访问名为 g_s
的共享指针的拥有对象。
我现在真的很迷茫。有人可以阐明这个问题吗?
std::shared_ptr<T>
保证对其控制块的访问是 thread-safe,但不能访问 std::shared_ptr<T>
实例本身,它通常是一个具有两个数据成员的对象:原始指针(由 get()
返回的那个)和指向控制块的指针。
在您的代码中,两个线程可能同时访问同一个 std::shared_ptr<int>
实例; f1
读取,f2
写入。
如果两个线程正在访问共享同一对象所有权的两个不同 shared_ptr
实例,则不会存在数据竞争。这两个实例将具有相同的控制块,但对控制块的访问将由库实现适当同步。
如果你需要并发,race-free从多个线程访问一个单个std::shared_ptr<T>
实例,你可以使用std::atomic<std::shared_ptr<T>>
. (There is also an older interface在 C++20 之前使用,在 C++20 中已弃用。)
众所周知,shared_ptr
仅保证对底层控制块的访问是线程
安全且不保证访问拥有的对象。
那为什么there is a race condition in the code snippet below:
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
}
在上面的代码片段中,确实没有访问名为 g_s
的共享指针的拥有对象。
我现在真的很迷茫。有人可以阐明这个问题吗?
std::shared_ptr<T>
保证对其控制块的访问是 thread-safe,但不能访问 std::shared_ptr<T>
实例本身,它通常是一个具有两个数据成员的对象:原始指针(由 get()
返回的那个)和指向控制块的指针。
在您的代码中,两个线程可能同时访问同一个 std::shared_ptr<int>
实例; f1
读取,f2
写入。
如果两个线程正在访问共享同一对象所有权的两个不同 shared_ptr
实例,则不会存在数据竞争。这两个实例将具有相同的控制块,但对控制块的访问将由库实现适当同步。
如果你需要并发,race-free从多个线程访问一个单个std::shared_ptr<T>
实例,你可以使用std::atomic<std::shared_ptr<T>>
. (There is also an older interface在 C++20 之前使用,在 C++20 中已弃用。)