C++怎么使用原子智能指针_C++atomic_shared_ptr实验特性【并发】

5次阅读

std::atomic_shared_ptr 不是标准c++特性,已被否决,当前编译器均不支持;应使用 std::atomic 并链接 -latomic(gcc/clang),或改用互斥锁等更稳妥方案。

C++怎么使用原子智能指针_C++atomic_shared_ptr实验特性【并发】

std::atomic_shared_ptr 是什么,现在能用吗

它不是标准 C++ 的正式特性,而是 C++20 中作为 std::atomic<:shared_ptr>></:shared_ptr> 的替代提案,在 TS(Technical Specification)中出现过,但最终被否决了。目前主流编译器(GCC、Clang、MSVC)**都不支持 std::atomic_shared_ptr 这个类型名**——你写上去会直接报错:Error: 'atomic_shared_ptr' is not a member of 'std'

真正可用的是 std::atomic<:shared_ptr>></:shared_ptr>,它从 C++20 起成为标准,但前提是你的 T* 必须是 trivially copyable(比如裸指针本身是,但 std::shared_ptr 内部结构是否可原子操作,取决于实现是否提供特化)。

常见错误现象:

  • 写了 std::atomic_shared_ptr<int></int>,编译失败
  • 写了 std::atomic<:shared_ptr>></:shared_ptr>,却在链接时报 undefined reference to __atomic_load_16(尤其在 x86-64 上)

为什么 std::atomic<:shared_ptr>> 链接失败

因为 std::shared_ptr 通常 16 字节(控制块指针 + 管理对象指针),而 x86-64 默认不支持原生 16 字节原子操作,需要编译器生成库级原子调用(如 __atomic_load_16),这依赖 libatomic。

立即学习C++免费学习笔记(深入)”;

实操建议:

  • 用 GCC/Clang 编译时,必须加 -latomic 链接选项(CMake 中: target_link_libraries(your_target atomic)
  • MSVC 没这个问题,它用内建函数或锁回退,但性能略低
  • 如果只在单核或确定无竞争场景用,其实没必要强上原子操作——std::shared_ptr 本身的引用计数已经是原子的,只是指针赋值不是

怎么安全地原子更新 shared_ptr 的指向

核心目标其实是:在线程中无锁地替换一个 std::shared_ptr<t></t> 变量的值(比如配置热更新、状态切换)。正确做法是用 std::atomic<:shared_ptr>></:shared_ptr> + load()/store() 或 CAS。

示例(注意对齐和初始化):

std::atomic<std::shared_ptr<int>> ptr; ptr.store(std::make_shared<int>(42)); // OK auto p = ptr.load();                   // OK ptr.exchange(std::make_shared<int>(100)); // OK

容易踩的坑:

  • 不能直接 ptr = std::make_shared<int>(42)</int> —— 会调用隐式转换构造,但该构造非原子,必须显式用 store()
  • 不要对 ptr.load()->value 做长时操作,因为指针可能中途被其他线程替换成新对象,旧对象已析构
  • 若 T 不是 trivially copyable(比如含虚函数、非 POD 类型),仍可工作,但原子操作本身只保证指针位模式的读写安全,不涉及 T 的构造/析构逻辑

有没有更轻量、更稳的替代方案

有。如果你只需要“原子地切换一个指针”,且不需要 shared_ptr 的共享语义,直接用 std::atomic<t></t> + 手动管理生命周期(比如配合 std::unique_ptr 或池化)更高效、更少陷阱。

或者用 std::shared_ptr 配合互斥锁(std::mutex),代码更直白、调试更友好,多数场景下性能差距远不如你想象的大。

真正复杂的地方在于:你以为你在解决并发指针更新问题,其实往往卡在内存序(memory order)选择、ABA 问题、或生命周期延长误判上——这些比选哪个原子类型难得多。

text=ZqhQzanResources