简体   繁体   English

关于使用 shared_ptr 的线程安全问题

[英]Question about the thread-safety of using shared_ptr

As it's well known that shared_ptr only guarantees access to underlying control block is thread safe and no guarantee made for accesses to owned object.众所周知, shared_ptr只保证对底层控制块的访问是线程安全的,不保证对拥有对象的访问。

Then why 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
}

In the code snippet above, the owned object of the shared pointer named g_s are not accessed indeed.在上面的代码片段中,名为g_s的共享指针的拥有对象确实未被访问。

I am really confused now.我现在真的很困惑。 Could somebody shed some light on this matter?有人可以对此事有所了解吗?

std::shared_ptr<T> guarantees that access to its control block is thread-safe, but not access to the std::shared_ptr<T> instance itself, which is generally an object with two data members: the raw pointer (the one returned by get() ) and the pointer to the control block. std::shared_ptr<T>保证对其控制块的访问是线程安全的,但不能访问std::shared_ptr<T>实例本身,它通常是一个具有两个数据成员的对象:原始指针(一个get()返回)和指向控制块的指针。

In your code, the same std::shared_ptr<int> instance may be concurrently accessed by the two threads;在您的代码中,两个线程可以同时访问同一个std::shared_ptr<int>实例; f1 reads, and f2 writes. f1读取, f2写入。

If the two threads were accessing two different shared_ptr instances that shared ownership of the same object, there would be no data race.如果两个线程正在访问共享同一对象所有权的两个不同shared_ptr实例,则不会发生数据竞争。 The two instances would have the same control block, but accesses to the control block would be appropriately synchronized by the library implementation.这两个实例将具有相同的控制块,但对控制块的访问将由库实现适当地同步。

If you need concurrent, race-free access to a single std::shared_ptr<T> instance from multiple threads, you can use std::atomic<std::shared_ptr<T>> .如果您需要从多个线程对单个std::shared_ptr<T>实例进行并发、无竞争的访问,则可以使用std::atomic<std::shared_ptr<T>> (There is also an older interface that can be used prior to C++20, which is deprecated in C++20.) (还有一个在 C++20 之前可以使用的旧接口,在 C++20 中已弃用。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM