shared_ptr 上的原子操作

Atomic operations on shared_ptr

假设我有 shared_ptr<T> a 和两个线程 运行ning,其中一个是:

a.reset();

还有一个:

auto b = a;

如果操作是原子的,那么我要么得到两个空的 shared_ptrs 或 a 是空的并且 b 指向 a 所指向的内容.我对这两种结果都满意,但是,由于指令的交错,这些操作可能不是原子的。有什么办法可以保证吗?

更准确地说,我只需要 a.reset() 是原子的。

UPD:正如评论中指出的那样,如果我不更具体一点,我的问题就很愚蠢。可以使用互斥体实现原子性。但是,我想知道在shared_ptr的实现层面上,事情是否已经得到解决。从 cppreference.com 开始,复制赋值和复制构造函数是线程安全的。所以 auto b = a 在没有锁的情况下 运行 是可以的。但是,从 this 开始,不清楚 a.reset() 是否也是线程安全的。

UPD1:如果有一些文档指定 shared_ptr 的哪些方法是线程安全的,那就太好了。来自 cppreference:

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

我不清楚哪些方法是非常量。

让另一个线程使用一个weak_ptr。弱指针上的 lock() 操作被记录为原子操作。

创建:

std::shared_ptr<A> a = std::make_shared<A>();
std::weak_ptr<A> a_weak = std::weak_ptr<A>(a);

线程 1:

a.reset();

线程 2:

b = a_weak.get();
if (b != nullptr)
{
    ...
}

std::shared_ptr<T> 就是有些人所说的 "thread-compatible" class,意思是只要 std::shared_ptr<T> 的每个 实例 在给定的时间点只能有一个线程调用其成员函数,这样的成员函数调用不会导致竞争条件,即使多个线程正在访问彼此共享所有权的 shared_ptrs。

std::shared_ptr<T> 不是 线程安全的 class;一个线程调用 std::shared_ptr<T> 实例的非 const 方法而另一个线程也在访问 同一实例 是不安全的。如果您需要潜在的并发读取和写入而不是竞争,则使用互斥锁同步它们。