You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程场景下弱指针未过期时的安全更新方法问询

问题

客户端持有指向线程安全对象(示例中用double代替)的std::shared_ptr,服务器在独立线程中通过std::weak_ptr对该对象执行更新操作。服务器原本的逻辑是先调用expired()检查weak_ptr是否过期,未过期则执行更新,但担心在expired()检查和更新操作的间隙,客户端的shared_ptr可能被销毁,导致访问非法内存。现寻求无需自定义原子变量或互斥量的实现方式,仅借助shared_ptr自带的原子计数器,确保检查和更新操作能在对象销毁前安全执行。

原代码示例

服务器代码

struct server
{
public:
    static void subscribe(const std::shared_ptr<double>& d)
    {
        m_values.safe_push_back(d); //线程安全的vector插入操作
    }

    void update()
    {
        auto updater = [](std::weak_ptr<double>& wd)
        {
            if(wd.expired()) wd = nullptr;
            else *wd += 2.0; //此处存在线程安全隐患?
        };
        m_values.safe_remove_all(nullptr);
        m_values.safe_visit(updater);
    };

private:
    static safe_vector<std::weak_ptr<double>> m_values;
}

客户端代码

struct client
{
    void subcribe_sleep_print(const double random_seconds)
    {
        std::shared_ptr<double> d = std::make_shared<double>(0.0); //示例中先创建对象再订阅
        server::subscribe(d);
        sleep_for_seconds(random_seconds); //随机休眠若干秒
        std::cout << *d << std::endl;
    }
}

注:实际场景中使用的是线程安全对象,+=操作本身是线程安全的。

解决方案

核心思路是通过**将weak_ptr原子性升级为shared_ptr**来消除竞态条件:std::weak_ptr::lock()方法会一次性完成「检查对象存活状态」和「增加引用计数」两个动作——如果对象未销毁,升级成功后引用计数加1,确保持有新shared_ptr期间对象不会被销毁;如果对象已销毁,lock()会返回空的shared_ptr。

修改后的服务器更新代码

void update()
{
    auto updater = [](std::weak_ptr<double>& wd)
    {
        if(auto sp = wd.lock()) //原子性升级为shared_ptr,彻底避免竞态
        {
            *sp += 2.0; //此时对象必然存活,操作安全
        }
        else
        {
            wd = nullptr; //对象已销毁,标记以便后续清理
        }
    };
    m_values.safe_remove_all(nullptr);
    m_values.safe_visit(updater);
};

原理说明

  • wd.lock()是线程安全的原子操作,完全规避了expired()检查与后续操作之间的时间窗口问题。
  • 只要sp这个临时shared_ptr的生命周期未结束,原对象的引用计数就不会降到0——哪怕客户端此时销毁了自己的shared_ptr,对象也会因为sp的存在继续存活,直到更新操作完成。
  • 当sp离开作用域时,引用计数自动递减,若此时没有其他shared_ptr持有对象,对象才会被销毁。

这种实现完全依赖shared_ptr自带的线程安全引用计数机制,不需要额外的互斥量或自定义原子变量,就能安全完成检查与更新操作。

内容的提问来源于stack exchange,提问作者SpeakX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 23:47:37