Rust 无锁结构中的内存回收:Epoch 与 Hazard Pointer 对比

先澄清核心矛盾 无锁链表里,线程 A 可能刚把节点从链表摘下,线程 B 还在读取它。此时直接 drop 会造成悬垂引用。 两类主流方案 Epoch Based Reclamation(EBR) 线程进入临界区时 pin 当前 epoch。 删除节点先放入 retired 列表。 只有当所有线程都跨过该 epoch,节点才可释放。 Hazard Pointer(HP) 读取前先声明“我正在看这个指针”。 回收线程扫描所有 hazard slot。 未被保护的 retired 节点才能释放。 EBR 的工程特性 吞吐通常更高,读路径开销小。 线程暂停会拖慢全局回收进度。 更适合短临界区、线程活跃的服务。 HP 的工程特性 回收更精细,不容易被慢线程拖住。 读路径需要发布 hazard,CPU 开销更高。 更适合线程生命周期不可控的系统。 Rust 落地建议 // 伪代码:删除节点不立即释放,而是 retire fn remove(node: Shared<Node>, guard: &Guard) { if cas_unlink(node, guard) { guard.defer_destroy(node); // 交给回收器延迟释放 } } 使用经过验证的库(如 crossbeam)而不是手搓回收器。 把“最大 retired 数量”做成指标,防止隐性内存膨胀。 压测时加入 SIGSTOP 慢线程场景,验证回收鲁棒性。 小结 锁不一定是瓶颈,错误回收一定是灾难。无锁结构上线前,先证明回收策略在“慢线程、抖动、长尾”下仍可控。

2026年4月28日 · 1 分钟 · BvBeJ