枚举ConcurrentDictionary时是否会遗漏枚举启动前的初始条目?
ConcurrentDictionary枚举初始条目完整性保障说明
这个行为是有.NET官方实现层面的机制保障的,你的测试结果并非随机巧合。
核心逻辑说明
官方文档提到枚举器不是时间点快照,仅指枚举过程中新增、修改、删除的内容不一定会完整体现在枚举结果中,并不代表枚举启动时已存在的条目会被遗漏:
- ConcurrentDictionary底层采用分桶存储的结构,每个哈希桶对应独立的锁。枚举器遍历每个桶时会先持有该桶的锁,遍历完当前桶内所有元素后再释放锁,因此遍历到对应桶时,桶内已存在的元素会被完整读取,不会被并发操作干扰。
- 所有枚举启动时就存在的初始条目,只要在枚举器遍历到它所属的哈希桶之前没有被其他线程删除,就一定会被枚举到。
场景适配建议
- 如果你的业务场景中,枚举过程中不会删除初始条目,完全可以依赖该特性直接枚举,不需要额外做快照,性能最优。
- 如果枚举过程中存在并发删除初始条目的逻辑,且你必须100%获取枚举启动时的全部条目,可以先调用
ToList()/ToDictionary()方法生成快照后再遍历快照,不过该操作会产生短暂的全局锁开销,性能低于直接枚举。
内容的提问来源于stack exchange,提问作者Jesús López
相关产品推荐
相关产品推荐

