假设我有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的非常量成员函数,那么将发生数据争用
我不清楚哪种方法是非常量的。
答案 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>
方法是不安全的,而另一个线程也在访问同一实例。如果您需要潜在的并发读写以防止竞争,请使用互斥锁对其进行同步。