std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争?

Is there any data race between std::weak_ptr and corresponding std::shared_ptr?

本文关键字:std ptr 存在 是否 数据 竞争 之间 weak shared      更新时间:2023-10-16

根据cppref的说法,跨多个线程访问shared_ptrconst成员是安全的。但是,当我们有一个对应于shared_ptrweak_ptr时,这种说法是否有效?

作为示例,假设以下代码:

#include <memory>
#include <iostream>
#include <thread>
std::shared_ptr<int> sp;
std::weak_ptr<int> gw;
int main()
{
sp = std::make_shared<int>(42);
gw = sp;
auto th1 = std::thread([]{
for (int i = 0; i < 200; i++) {
if (sp.use_count() > 1) {
std::cout << i << "n";
std::this_thread::yield();
}
}
});
auto th2 = std::thread([]{
for (int i = 0; i < 20; i++) {
if (auto l = gw.lock()) {
std::cout << "locked ->" << l.use_count() << "n";
std::this_thread::yield();
}
}
});
th1.join();
th2.join();
}

此代码创建 2 个线程。一个检查shared_ptr()use_count(),这是一种const方法,另一个使用lock()来锁定weak_ptr()这也是一种const方法。但实际上,当我在weak_ptr上调用lock时,我实际上增加了shared_ptr的引用计数,除非引用计数在内部受到保护,否则这不是线程安全的。我想知道在这种情况下我是否会进行数据竞赛。按照标准,这应该是线程安全的吗?

是的。引用计数器是原子计数器,因此示例中没有数据争用。

话虽如此,std::shared_ptr指向的对象上的可变操作不是原子的,因此必须像通过普通指针保护访问一样保护它们。