首页 > 解决方案 > std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争?

问题描述

根据 cppref,跨多个线程访问const成员是安全的。shared_ptr但是,当我们有weak_ptr对应于 a 的a 时,这个陈述是否有效shared_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 个线程。其中一个检查use_count()shared_ptr()一种const方法,另一个lock()用于锁定weak_ptr(),这也是一种const方法。但实际上,当我调用lockweak_ptr,我实际上会增加引用计数,shared_ptr除非引用计数在内部受到保护,否则它不是线程安全的。我想知道在这种情况下我是否会进行数据竞赛。按照标准,这应该是线程安全的吗?

标签: c++language-lawyer

解决方案


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

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


推荐阅读