Facebook folly::ConcurrentHashMap迭代器线程安全性及失效问询
关于folly::ConcurrentHashMap迭代器失效的风险分析
先把你的场景代码明确出来:
folly::ConcurrentHashMap<std::string, some_class> m; // 添加一些元素 const auto it = m.find("a"); // 此时另一个线程移除了"a"元素 if (it != m.end()) it->second.something(); // 此时该迭代器是否已失效?
好消息是,这个场景下你完全不用担心迭代器失效的问题——这正是folly::ConcurrentHashMap针对并发访问场景设计的核心安全特性之一。
结合你提到的源码细节,具体的逻辑是这样的:
- 当你调用
find()获取迭代器时,这个迭代器会持有一个指向目标元素的风险指针(hazard pointer) - 风险指针的核心作用就是“保护”元素内存:只要当前线程还持有这个指针,其他线程就无法真正销毁该元素的内存空间
- 当另一个线程调用
erase()移除"a"元素时,它会先检查是否有线程持有该元素的风险指针:- 如果检测到风险指针存在,元素只会被标记为已删除状态,但不会立即释放内存
- 只有当持有风险指针的线程使用完迭代器(比如迭代器被销毁、或者主动释放了风险指针),对应的元素内存才会被安全回收
对应到你的代码流程:
- 线程A调用
find("a")拿到迭代器it,此时it持有"a"元素的风险指针,元素内存被保护 - 线程B调用
erase("a"),发现元素被风险指针保护,仅标记元素为已删除,不会释放内存 - 线程A执行
if (it != m.end()) it->second.something();时,虽然元素已经被标记为删除,但迭代器仍然有效,内存也未被释放,所以访问it->second是完全安全的 - 当线程A的迭代器
it被销毁(比如离开当前作用域),风险指针被释放,此时线程B之前标记的元素才会被真正销毁
额外提醒一句:如果你后续再调用find("a"),会返回m.end(),因为元素已经被标记为删除;但你之前已经持有的迭代器,在它被销毁前都可以安全访问元素的内容。
内容的提问来源于stack exchange,提问作者Michael Smith
相关产品推荐
相关产品推荐

