分段锁通过将哈希表划分为多个独立段并为每段配专属锁,实现非冲突段操作的完全并行;无锁链表利用原子指针与CAS实现单桶内插入/查找的零阻塞;混合策略则在分段基础上对小段采用无锁优化、大段保留互斥锁,兼顾性能与内存管理简洁性。

如果您需要在多线程环境中高效存取键值对,而标准库的 std::unordered_map 无法满足并发安全与吞吐量要求,则需自行实现支持高并发访问的哈希表。以下是基于原子操作与分段锁策略的三种核心实现方法:
一、分段锁(Striped Locking)实现
该方法将哈希表划分为多个独立段(segment),每段拥有专属互斥锁,使不同线程对非冲突段的操作完全并行,显著降低锁竞争。
1、定义段数组,每个段为一个独立的桶链表结构,并配以 std::mutex 成员。
2、哈希函数输出经模运算映射到段索引: segment_index = hash(key) % num_segments。
3、插入时先锁定对应段,遍历该段内桶链表,若键已存在则更新值;否则头插新节点。
4、查找时仅锁定目标段,遍历链表比对键,命中即返回值引用,未命中返回默认构造值或抛异常。
5、删除操作同样只锁定单一段,在链表中定位并移除节点,注意维护指针与内存释放顺序。
二、无锁链表 + 原子指针(Lock-Free Bucket List)实现
针对单个桶链表,使用 std::atomic
1、定义节点结构体,其中 next 指针声明为 std::atomic
2、插入新节点时,读取当前桶头指针 old_head,构造新节点并设置其 next 为 old_head,再用 compare_exchange_weak 尝试将桶头更新为新节点地址。
3、若 CAS 失败,说明其他线程已修改头指针,重新读取 old_head 并重试,直至成功。
4、查找操作无需原子写,仅需按序遍历由原子指针串联的节点链,但须确保节点内存生命周期在查找期间有效(如采用引用计数或 epoch-based 内存回收)。
5、删除操作不可简单解链,必须结合标记删除(tagged pointer)或延迟回收机制防止 ABA 问题。
三、混合策略:分段锁 + 每段内原子操作优化
在分段锁基础上,对各段内部进一步优化:小段采用无锁链表提升热点桶性能,大段仍保留细粒度互斥锁以简化内存管理逻辑,兼顾安全性与效率。
1、设定阈值(如段内节点数 ),低于阈值的段启用原子头指针链表,高于阈值则切换为带锁的动态数组+开放寻址结构。
2、段结构体中嵌入联合体(union),包含 std::atomic
3、插入前检查段大小,若触发阈值则先获取段锁,完成模式切换与数据迁移,再执行对应路径的插入逻辑。
4、所有跨段操作(如 rehash)必须按固定顺序获取全部段锁,避免死锁,例如始终按段索引升序加锁。
5、rehash 触发条件设为全局负载因子超过 0.75,新表容量为旧表两倍,迁移过程逐段加锁并批量转移节点。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











