我正在编写一个网络服务,它接收原始数据包然后转换它们并将它们放入队列中,还有一些工作线程从队列中获取转换后的数据包,并根据一些规则更新哈希映射。为了防止来自不同工作线程的哈希映射的并发更新,我必须使用互斥锁。不幸的是,使用互斥锁会带来巨大的性能损失。我需要为此找到一个解决方法。
EDITED: 转换后的数据包包含 sessio_id ,此session_id用作哈希地图键。在任何插入或更新之前,session_id首先已搜索,如果找不到session_id,则新条目已添加且这正是我使用互斥锁< / strong>,否则如果session_id已经存在,我只需更新现有值,并且没有用于单纯值更新的互斥锁。它可能有助于我知道我使用 boost :: unordered_map 作为底层哈希映射。
下面的是我使用的逻辑的psudo代码:
if hash.find(session_id) then
hash.update(value)
else
mutex.lock()
hash.insert(value)
mutex.unlock()
end
你的建议是什么?
顺便说一下,这是我的工作环境和工具:
编译器:C ++(gcc)
线程库:pthread
操作系统:Ubuntu 14.04
答案 0 :(得分:2)
最快的解决方案是以每个线程使用自己的数据集的方式拆分数据,因此根本不需要任何锁定。也许你可以通过基于一些关键数据在线程之间分发消息来实现目标。
第二个最佳解决方案是使用C ++ 11原子或C库中的函数实现读写自旋锁,请参阅https://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
读写自旋锁通常允许多个并行读访问,但只有一个写访问(当然也阻止所有读访问)。
在Linux中也有一个读写互斥锁,但我发现它比手工制作的实现稍慢。
答案 1 :(得分:0)
您是否研究过无锁数据结构?你可以参考Andrei Alexandrescu和Maged Michael撰写的一篇有趣的论文Lock-Free Data Structures with Hazard Pointers。例如,可以在libcds Github存储库中找到使用类似想法的一些实现。
虽然他们在某种程度上使用锁定,但Facebook的folly AtomiHashMap和英特尔的TBB也提供了高性能的并发哈希映射。
当然,这些方法需要额外的阅读和集成工作,但如果您确定当前的锁定策略是瓶颈,那么它可能是值得的。