C++ 同时重置和复制共享\u ptr是否线程安全?

C++ 同时重置和复制共享\u ptr是否线程安全?,c++,thread-safety,shared-ptr,C++,Thread Safety,Shared Ptr,描述从多个线程同时访问共享指针时的行为。特别是他们举了一些例子: shared_ptr<int> p(new int(42)); //--- Example 1 --- // thread A shared_ptr<int> p2(p); // reads p // thread B shared_ptr<int> p3(p); // OK, multiple reads are safe //--- Example 2 --- // thread

描述从多个线程同时访问共享指针时的行为。特别是他们举了一些例子:

shared_ptr<int> p(new int(42));

//--- Example 1 ---

// thread A
shared_ptr<int> p2(p); // reads p

// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe

//--- Example 2 ---

// thread A
p.reset(new int(1912)); // writes p

// thread B
p2.reset(); // OK, writes p2

//--- Example 3 ---

// thread A
p = p3; // reads p3, writes p

// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
...
所以我的问题是最后一个例子是否正确

注意:Boost的第三个例子解释了并行读写同一个对象是不安全的。但在他们的例子中,他们将
p3
分配给
p
,这是
p3
的副本。因此,我不清楚该示例的安全性是否取决于
p3
被分配到其副本的事实,或者其他内容是否不安全

但是他们没有说(或者我看不到)如果同时写入和读取同一个共享的\u ptr对象会发生什么

是的,他们有:

一个
共享的\u ptr
实例可以由多个线程同时“读取”(仅使用常量操作访问)。不同的
shared_ptr
实例可以由多个线程同时“写入”(使用可变操作,如
operator=
reset
)来访问)(即使这些实例是副本,并且在下面共享相同的引用计数。)

任何其他同时访问都会导致未定义的行为。

(强调矿山)

我似乎很清楚

所以我的问题是最后一个例子是否正确

不,因为您所做的不是从单个实例同时读取,也不是向单独的实例写入。您正在同时读取和写入单个实例。这是一种数据竞争,而且是未定义的行为。

现在我们有了C++11(和14/17),您可以使用原子共享指针类以原子方式处理线程中的共享指针


简单地说,如果您可能最终修改了一个共享指针,那么您应该到处使用原子函数(所有读取和所有写入)。然后您的线程不应该因为共享指针而崩溃。

您的示例与他们的示例完全相同-一个线程读取
p
,一个线程写入
p
,所以它不可能是安全的。@molbdnilo在他们的例子中,他们写信给
p
(p3的副本)和
p3
,所以我认为不安全可以依赖于这个事实。不,这是无关的。这些例子只是为了说明一些例子,而不是所有可能的例子。顶部的文本是你需要阅读的最终答案,非常清楚。@JonathanWeakey现在,在你的答案对我来说很清楚了,谢谢。但是现在它是(在C++20中被弃用)@Alex,你知道它被弃用的原因吗?C++20建议
std::atomic
因为
std::shared_ptr
不是可复制的,所以在
std::atomic中似乎
T
可以是不可复制的,或者
std::shared\u ptr
变得不可复制了。
shared_ptr<int> p(new int(42));

//--- My Example ---

// thread A
p.reset(new int(1912));

// thread B
shared_ptr<int> p1 = p;