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

指向const对象的shared_ptr线程安全性及锁保护需求咨询

线程安全的shared_ptr持有const map场景问题

场景与代码

现有场景:线程持有指向const map<int, string>对象的shared_ptr,该shared_ptr会被其他线程偶尔更新,同时也会被不同线程读取。代码实现如下:

class SharedPointerHolder {
  private:
    shared_ptr<const map<int, string>> sptr_;
  public:
    SharedPointerHolder() : sptr_(make_shared<const map<int, string>>()) {};
    // new_sptr is guaranteed to be a valid pointer.
    void UpdateSharedPointer(shared_ptr<const map<int, string>>&& new_sptr) {
      if (!new_sptr) { return; }
      sptr_ = move(new_sptr);
    }
    void ReadSharedPointer() {
      // Since only UpdateSharedPointer() updates sptr_, it is guaranteed that sptr_ will always be valid. Still just in case, I have added this "if".
      if (!sptr_) {
        return;
      }
      auto local_sptr = sptr_;
      // Read the map object pointed by the local_sptr and perform some operations.
    }
};

疑问

  1. 当前UpdateSharedPointer()不会被多线程同时调用,请问sptr_是否需要通过锁保护?本人了解到锁用于保护shared_ptr指向的数据,而本次数据为const类型,且可接受读取脏数据,认为无需锁。
  2. 若UpdateSharedPointer()可能被多线程同时调用,除了脏数据容忍度外,是否存在其他需关注的竞态条件?核心担忧是数据损坏问题。

解答

1. 单线程调用UpdateSharedPointer时的锁需求

需要加锁,核心原因不是脏数据,而是普通shared_ptr的读写不同步会触发未定义行为:

  • shared_ptr内部包含对象指针和控制块指针(存储引用计数等信息),其赋值/移动赋值操作并非原子操作——修改sptr_时会分步骤更新这两个指针。如果读线程刚好在写线程修改的间隙读取sptr_,可能拿到一个内部状态不一致的shared_ptr(比如对象指针是新的,但控制块还是旧的),后续对这个shared_ptr的操作(如拷贝、访问对象)会导致不可预测的错误,甚至程序崩溃。
  • 你提到可接受脏数据(读取旧的map实例),加锁完全不影响这个需求:锁只会保证读取到的sptr_是完整的(要么是旧的完整实例,要么是新的完整实例),不会出现中间损坏的状态。如果使用C++20及以后的atomic<shared_ptr<T>>存储sptr_,也可以通过原子操作实现线程安全,无需手动加锁。

2. 多线程调用UpdateSharedPointer时的额外风险

当UpdateSharedPointer()被多线程同时调用时,除了脏数据问题,还存在严重的数据竞争导致的sptr_损坏风险:

  • 多个线程并发执行sptr_ = move(new_sptr)时,会同时修改sptr_的内部状态,直接触发数据竞争,属于未定义行为。可能出现旧控制块的引用计数未正确递减,引发内存泄漏;或者引用计数被错误修改,导致map对象被提前释放,后续访问出现野指针。
  • 即使能接受脏数据,这种场景下读线程也可能拿到完全无效的shared_ptr,直接导致程序崩溃。

因此这种情况下必须用锁(比如std::mutex)保护sptr_的所有读写操作,确保同一时间只有一个线程修改sptr_,且读取操作不会与修改操作重叠。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:15:32