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

无并发访问时,生产者消费者间使用std::shared_ptr及移除mutex的安全性问题

关于std::shared_ptr线程安全及示例代码mutex移除的问题

一、先明确std::shared_ptr的线程安全范围

别被“shared_ptr线程安全”的说法误导——它的安全边界有明确限制:

  • 多个线程同时读同一个shared_ptr对象:安全;
  • 多个线程同时修改不同的shared_ptr对象(哪怕指向同一个托管实例):安全,因为引用计数的增减是原子操作;
  • 多个线程同时读写同一个shared_ptr对象:不安全!因为shared_ptr的赋值/拷贝除了原子更新引用计数,还涉及内部指针的修改,这部分不是原子的,会导致读取到半更新的无效状态。

回到你第一个问题:如果说的是托管的对象(比如示例里的Demo实例)不会被同时访问,那shared_ptr的使用没问题;但如果是shared_ptr对象本身被多线程读写,哪怕托管对象不同时访问,也必须加同步保护。

二、示例代码里的mutex不能直接移除

看你的代码逻辑:

  • front_result被producer1线程写(SetFrontRes里赋值),同时被MergeResults线程读(拷贝到cur_front_res);
  • back_result同理,属于单写多读的shared_ptr对象。

这种场景下,mutex是必须的——如果去掉,读写操作不同步,可能出现MergeResults拿到半更新的front_result,导致后续访问cur_front_res->i时出现野指针、内存泄漏甚至程序崩溃。

替代方案:用std::atomicstd::shared_ptr(C++20+)

如果你的项目支持C++20,可以把成员变量改成原子shared_ptr,这样就能去掉mutex:

// 替换原有的成员变量
std::atomic<SCDemoPtr> front_result;
std::atomic<SCDemoPtr> back_result;

// 修改SetFrontRes
void ResultManager::SetFrontRes(SCDemoPtr oms_res) {
    front_result.store(oms_res, std::memory_order_release);
}

// 修改MergeResults里的读取逻辑
cur_front_res = front_result.load(std::memory_order_acquire);

std::atomic<std::shared_ptr>专门实现了原子的赋值和加载操作,能保证线程安全,不需要额外的mutex。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:40:18