shared_ptr上的原子操作

时间:2018-11-15 17:15:46

标签: c++ multithreading atomic

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

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:

  

如果多个执行线程在不同步的情况下访问同一个shared_ptr,并且其中任何访问使用了shared_ptr的非常量成员函数,那么将发生数据争用

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

2 个答案:

答案 0 :(得分:2)

让另一个线程使用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)
{
    ...
}

答案 1 :(得分:2)

std::shared_ptr<T>被某些人称为“线程兼容”类,这意味着,只要std::shared_ptr<T>的每个 instance 只能有一个线程调用其成员函数在给定的时间点,即使多个线程正在访问彼此共享所有权的shared_ptr,这种成员函数调用也不会引起竞争条件。

std::shared_ptr<T>不是线程安全类;一个线程调用const实例的非std::shared_ptr<T>方法是不安全的,而另一个线程也在访问同一实例。如果您需要潜在的并发读写以防止竞争,请使用互斥锁对其进行同步。