如何优雅解决线程安全Map单行操作的死锁问题?
线程安全std::map容器tsmap的死锁规避与优化实践
问题背景
基于std::map实现了线程安全容器tsmap,通过LockProxy封装std::shared_mutex实现读写锁控制。但在执行同一容器内的单行跨成员复制操作时(例如:
*map_mem.unique_lock(-12345)[4] = *map_mem.unique_lock(-12345)[3]
),必须通过自定义ident标识避免重复加锁导致的死锁,这种实现不够优雅,需要更简洁的解决方案。
优化方案迭代
1. 基于线程ID的自动锁跟踪
放弃自定义ident,改用std::this_thread::get_id()获取当前线程ID作为锁的跟踪标识:
- 当同一线程再次请求对同一容器加锁时,容器内部通过线程ID识别出是同一持有者,直接允许获取锁(无需实际重复加锁),从根源避免死锁。
- 这种方式无需业务代码传入额外标识,完全由容器内部自动处理,代码更简洁直观。
2. 扩展兼容标准锁接口
对tsmap的锁接口进行扩展,支持std::scoped_lock等C++标准锁类型:
- 让容器的锁操作与标准库锁机制对齐,降低学习成本,同时提升代码的兼容性和可维护性。
- 例如可以实现支持
std::scoped_lock的构造重载,允许直接将容器的锁对象传入标准锁进行管理。
性能验证
优化后的tsmap经过高并发场景测试,性能表现优异,既解决了死锁问题,又保持了读写锁带来的并发效率优势。
内容的提问来源于stack exchange,提问作者michaeladm
相关产品推荐
相关产品推荐

