为什么map在C ++中不是多线程安全的?

时间:2013-08-22 15:10:48

标签: c++ multithreading map

当我尝试在代码中解决并发问题时,我遇到了这个问题。在原始代码中,我们只使用一个唯一的锁来锁定作为stl映射的缓存的写操作。但是对缓存的读操作没有限制。所以我想在读操作中添加一个共享锁,并保持对写操作的唯一锁。但是有人告诉我,由于它本身就存在一些内部缓存问题,在地图上进行多线程处理是不安全的。

有人可以详细解释原因吗?内部缓存有什么作用?

4 个答案:

答案 0 :(得分:6)

std::map的实现必须符合常规 保证:如果您的所有内容都被阅读,那就没有必要了 外部同步,但只要一个线程修改, 所有次访问必须同步。

我不清楚“共享锁”是什么意思;没有 这样的事情在标准中。但是,如果任何一个线程正在写 您必须确保没有其他线程可以同时读取。 (可以使用像Posix'pthread_rwlock这样的东西,但是 标准中没有类似的东西,至少我不能这样 找到手。)

答案 1 :(得分:1)

可以从C ++ 11中的多个线程安全地调用const类型的所有std个成员函数,而无需显式同步。实际上,任何与标准库一起使用的类型(例如,作为容器的模板参数)都必须满足此保证。

Clarificazion:该标准保证您的程序具有所需的行为,只要您不会在没有同步点的情况下对同一数据位置进行写入和任何其他访问。这背后的基本原理是现代C​​PU没有严格的顺序一致的内存模型,这将限制可扩展性和性能。在引擎盖下,您的编译器和标准库将在需要更强内存排序的位置发出适当的内存栅栏。

答案 2 :(得分:1)

至少从C ++ 11开始,对标准库类的const操作保证是线程安全的(假设对存储在其中的对象的const操作是线程安全的。)

答案 3 :(得分:1)

我真的不明白为什么会有任何缓存问题......

如果我引用map的stl定义,则应将其实现为binary search tree

二叉搜索树只是一个带有键值节点池的树。这些节点按其键的自然顺序排序,为避免任何问题,键必须是唯一的。因此,根本不需要内部缓存。

由于不需要内部缓存,因此读取操作在多线程上下文中是安全的。但是对于那些必须为任何非线程感知数据结构提供自己的同步机制的人来说,写操作的故事并不相同。

请注意,当线程执行写操作时,您还必须禁止任何读操作,因为此写操作可能导致二进制树的缓慢和完全重新平衡,即在长写期间快速读取操作操作会返回错误的结果。