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

为何C++标准库shared_ptr递减原子引用计数使用acq_rel内存序?

shared_ptr控制块引用计数内存序设计解析

为什么递增用relaxed内存序?

  • 引用计数递增的核心需求只是保证计数本身的原子性,不需要同步其他内存状态。当拷贝shared_ptr时,控制块里的对象指针、析构函数等关键数据在创建时就已经完全初始化,新的shared_ptr实例不需要通过递增计数来同步这些数据。
  • relaxed是最轻量级的内存序,不会插入任何内存屏障,仅保证原子操作的正确性,能最大化提升高频拷贝操作的性能。

为什么递减用acq_rel内存序?

  • 递减操作的核心风险是计数归零时要销毁对象和控制块,这时候必须满足两个同步要求:
    1. acquire语义:确保当前线程中所有对共享对象的读写操作,在执行销毁动作前都已完成并可见,避免销毁时对象仍被使用。
    2. release语义:确保计数递减到0的结果能被其他线程及时看到,防止其他线程访问已销毁对象,同时避免多线程重复触发销毁逻辑(双重释放)。
  • acq_rel内存序同时满足这两个需求,既保证当前线程操作的完成性,又保证计数状态的全局可见性。

为什么不采用“递增release、递减acquire”的组合?

  • 递增用release完全冗余:release语义会强制后续内存操作不能重排到递增之前,但拷贝shared_ptr后的操作(比如访问对象)根本不需要这种强约束——控制块的初始化早于任何拷贝操作,release只会额外插入内存屏障,徒增性能开销。
  • 递减用acquire不足以保证安全:acquire仅能保证当前线程看到之前的操作,但无法确保其他线程及时感知计数变为0的状态。多线程同时递减时,可能出现多个线程都认为自己是最后持有者,重复执行销毁逻辑,引发未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:52:07