是否可以同时重置和复制shared_ptr的线程安全?

Mih*_*yan 10 c++ thread-safety shared-ptr

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

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
...
Run Code Online (Sandbox Code Playgroud)

但他们没有说(或者我看不到)如果同时shared_ptr写入和读取同一个对象会发生什么.说:

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

//--- My Example ---

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

// thread B
shared_ptr<int> p1 = p;
Run Code Online (Sandbox Code Playgroud)

所以我的问题是最后一个例子是否合适?

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

Jon*_*ely 14

但他们并没有说(或者我看不到)如果同时写入和读取相同的shared_ptr对象会发生什么.

是的他们这样做:

shared_ptr由多个线程实例可以是"读"(仅使用常量操作访问)同时进行.不同的shared_ptr实例可以被多个线程同时"写入"(使用operator=或等可变操作访问reset)(即使这些实例是副本,并在下面共享相同的引用计数.)

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

(强调我的)

对我来说似乎很清楚.

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

不,因为您所做的不是从单个实例同时读取,也不是写入单独的实例.您正在同时阅读和编写单个实例.这是一场数据竞赛和未定义的行为.