在 Rainer Grimm 的书中, Concurrency with Modern C++
这些代码行:
std::shared_ptr<int> ptr = std::make_shared<int>(2011);
for (auto i=0; i<10; i++){
std::thread([&ptr]{
ptr = std::make_shared<int>(2014);
}
).detach();
}
有一个说法:
lambda 函数通过引用绑定第 4 行中的 std::shared_ptr ptr。这意味着,赋值(第5行)可能会变成底层资源的并发读写;因此,该程序具有未定义的行为。
告诉我为什么行为会是未定义的?在我看来,这与cppreference相矛盾
所有成员函数(包括复制构造函数和复制赋值)都可以由共享_ptr 的不同实例上的多个线程调用,而无需额外的同步,即使这些实例是同一对象的副本并共享所有权。
“我假设shared_ptr控制块受到保护” ——就是这样。只有这个受保护的控制块不包含在
ptr
. 并且与您自己的操作ptr
不受保护。问题中的引用指的是从不同线程访问不同实例的情况
shared_ptr
,这些实例可能共享同一对象的所有权。在代码中存在从不同线程访问同一实例的情况shared_ptr
: