c++26标准库中不存在hazard pointers相关设施,因其对abi、调度和编译器优化要求极高且缺乏跨平台共识;标准未定义线程局部slot管理、scan时机及专用barrier语义,故无法仅靠std::atomic模拟。

hazard pointers 在 C++26 标准库中根本不存在
C++26 没有加入 hazard_pointers、hazard_register 或任何与 hazard pointer 直接对应的类型或设施。标准库仍不提供无锁内存回收(lock-free memory reclamation)的原语——这不是遗漏,而是有意推迟:这类机制对 ABI、调度语义、编译器优化约束极强,目前缺乏跨平台共识实现。
为什么你不能直接用 std::atomic + hazard_pointers 模拟标准支持
常见误解是“既然有 std::atomic,我手写 hazard pointer 就行”。但问题不在原子操作本身,而在三个硬性缺失:
- 没有标准化的线程局部 hazard slot 管理(
hazard_pointer::retire()类接口需全局协调) - 没有定义
scan()时机和语义:何时清理 retired list?由谁触发?是否阻塞?C++ 标准不规定线程协作模型 -
std::atomic_thread_fence的语义不足以替代专用 barrier(如 HP 的 quiescent state barrier),尤其在弱内存序平台(ARM、RISC-V)上易出现 ABA 变体或提前释放
当前可行路径:依赖成熟第三方库而非标准库
真要落地 hazard pointer,实际项目中只有两条路可走,且都绕不开外部依赖:
- 用
libcds:提供完整cds::gc::hzp::GarbageCollector,支持动态线程注册、自动 scan 调度、多种 retire 策略;但要求显式调用hzp::GarbageCollector::instance().scan()或启用后台线程 - 用
folly::hazptr:Facebook 维护,API 更轻量(folly::hazptr_holder+retire()),默认延迟回收,但需注意其依赖folly::SingletonThreadLocal,在 dlopen 场景下可能初始化失败 - 自研必须重做三件事:线程局部 hazard array 分配、全局 retired list 的无锁合并、以及 safe-to-reclaim 判定(不能只靠 refcount,必须结合 epoch 或 quiescence)
别把 std::atomic<:shared_ptr></:shared_ptr> 当成无锁替代方案
有人试图用 std::atomic<:shared_ptr>></:shared_ptr> 实现无锁结构,这是危险的简化:
-
std::shared_ptr的控制块更新不是无锁的(内部用 mutex 或 CAS loop,但非 lock-free) - 引用计数递增/递减本身是原子的,但
delete时机不可控:析构可能发生在任意线程,导致 use-after-free(尤其在 hazard pointer 场景下,reader 还在 dereference,writer 已 delete) - 即使搭配
std::atomic_thread_fence(std::memory_order_release),也无法保证其他线程看到“对象已不可访问”的全局视图——这正是 hazard pointer 要解决的核心问题
真正难的不是写一个 load() 或 store(),而是让所有 reader 和 writer 对“某块内存是否还能被访问”达成一致判断。这个一致性边界,C++ 标准库至今没划。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











