当前位置: 首页 > news >正文

std::shared_ptr 的线程安全性

1. 引用计数的线程安全性

  • 完全线程安全shared_ptr 的引用计数机制本身是线程安全的,这是通过原子操作实现的。

  • 实现原理

    // 伪代码示意
    class control_block {std::atomic<long> ref_count;  // 原子引用计数//...
    };void increment_ref_count() {ref_count.fetch_add(1, std::memory_order_relaxed);
    }void decrement_ref_count() {if (ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {delete managed_object;  // 安全删除对象}
    }
    • 使用 std::atomic 保证引用计数的增减是原子操作

    • 增加计数用 memory_order_relaxed(只需原子性,无顺序约束)

    • 减少计数用 memory_order_acq_rel(保证删除对象前的所有操作可见)

2. 指向对象的线程安全性

  • 非线程安全shared_ptr 不保证其管理的对象是线程安全的

    // 危险示例:多个线程同时修改同一对象
    std::shared_ptr<int> p = std::make_shared<int>();void thread_func() {p->value++;  // 非原子操作,数据竞争!
    }

    需要额外同步机制(如互斥锁)保护对象内部状态。


3. shared_ptr 实例本身的线程安全性

操作类型线程安全性示例
多个线程同一实例✅ 安全auto p2 = p1;(拷贝构造)
多个线程写不同实例✅ 安全p1.reset(); p2.reset();
多个线程写同一实例❌ 不安全(需加锁)p1 = p2;(赋值操作竞争)

关键机制解析

  1. 原子引用计数的实现

    • 控制块(control block)中的计数器使用原子类型

    • 增减操作通过 CPU 级原子指令实现(如 x86 的 LOCK XADD

    • 保证即使多线程同时拷贝/析构,引用计数也准确

  2. 内存序的作用:

    memory_order_acq_rel 在减少计数时确保:删除对象前,所有线程对对象的操作已完成;避免指令重排序导致对象提前释放
  3. 对象删除安全性
    // 删除对象时的保护逻辑
    if (ref_count.fetch_sub(1) == 1) {  // 原子减后判断// 只有最后一个持有者执行删除delete ptr; 
    }


线程安全使用指南

  1. 安全模式

    // 多线程共享只读对象
    std::shared_ptr<const Config> config = load_config();
    // 所有线程安全读取 config->getValue()
  2. 需加锁场景

    std::shared_ptr<Data> resource;
    std::mutex mtx;void update() {std::lock_guard<std::mutex> lk(mtx);resource = std::make_shared<Data>(new_data); // 安全更新
    }
  3. 高效跨线程传递

    // 使用 std::move 避免原子操作开销
    std::shared_ptr<Job> job = create_job();
    std::thread worker([job = std::move(job)] {// 独占使用,无引用计数开销
    });
  4. 弱引用解决循环依赖

    std::weak_ptr<Node> weak_node = node;
    if (auto locked = weak_node.lock()) { // 原子检查// 安全使用 locked
    }

相关文章:

  • Java基础 6.21
  • cursor中定义cursor rules
  • 【Elasticsearch】运维监控:分片和节点
  • 当数据自己会说话:聚类与分类算法全景解析
  • P1220 关路灯
  • AI大模型学习之基础数学:微积分-AI大模型的数学引擎
  • nn4dms开源程序是用于深度突变扫描数据的神经网络
  • 安装 Labelme
  • 如何使用Ant Design Blazor组件在列表页弹窗增加修改数据
  • C++ 文件读写
  • 并查集(Disjoint-Set Union)详解
  • 单点登录(SSO)系统
  • SpringAI1.0.0 入门案例
  • 教育培训APP源码核心功能开发详解:直播、考试、组卷系统全拆解
  • GNU Octave 基础教程(8):GNU Octave 常用数学函数
  • nginx服务器配置时遇到的一些问题
  • 从0开始学习计算机视觉--Day02--数据驱动
  • 一、什么是生成式人工智能
  • linux生产环境下根据关键字搜索指定日志文件命令
  • 嵌入式开发之嵌入式系统硬件架构设计时,如何选择合适的微处理器/微控制器?
  • 可视化 网站开发工具/杭州最专业的seo公司
  • 由一个网页建成的网站/今日新闻网
  • wordpress文章管理/什么是seo网站优化
  • 网站全网建设 莱芜/安卓优化大师旧版
  • 怎么做网站的后台管理系统/百度指数里的资讯指数是什么
  • 吕子乔做网站一段台词/免费网站大全