为什么映射在C++中不是多线程安全的
Why map is not multithread safe in C++?
我在试图解决代码中的并发问题时遇到了这个问题。在原始代码中,我们只使用一个唯一的锁来锁定作为stl映射的缓存上的写操作。但是对缓存的读取操作没有限制。所以我想在读操作中添加一个共享锁,并在写操作中保留唯一锁。但有人告诉我,在映射上执行多线程是不安全的,因为它本身存在一些内部缓存问题。
有人能详细解释一下原因吗?内部缓存的作用是什么?
std::map
的实现都必须满足保证:如果您的所有操作都已阅读,则无需外部同步,但只要一个线程修改,所有访问都必须同步。
我不清楚你所说的"共享锁"是什么意思;没有标准中有这样的东西。但是如果有一个线程在写,您必须确保没有其他线程可以同时读取。(可以使用类似Posix’pthread_rwlock
的东西,但是标准中没有类似的东西,至少我不能找到现成的。)
至少由于C++11,标准库类上的const
操作保证是线程安全的(假设对存储在其中的对象的const
操作是线程安全)。
std
类型的所有const
成员函数都可以在C++11中从多个线程安全地调用,而无需显式同步。事实上,任何与标准库结合使用的类型(例如,作为容器的模板参数)都必须满足这一保证。
Clarificazion:该标准保证您的程序将具有所需的行为,只要您永远不会在没有同步点的情况下对同一数据位置进行写入和任何其他访问。这背后的理由是,现代CPU没有严格的顺序一致的内存模型,这会限制可扩展性和性能。在引擎盖下,编译器和标准库将在需要更强内存顺序的地方发出适当的内存围栏。
我真的不明白为什么会有任何缓存问题。。。
如果我引用映射的stl定义,那么它应该实现为二进制搜索树。
二进制搜索树只是一个具有键值节点池的树。这些节点按照其键的自然顺序进行排序,为了避免任何问题,键必须是唯一的。因此根本不需要内部缓存。
由于不需要内部缓存,读取操作在多线程环境中是安全的。但是,对于写操作,情况就不一样了,对于那些必须提供自己的同步机制的写操作,就像对于任何非线程感知的数据结构一样。
请注意,当线程执行写入操作时,您还必须禁止任何读取操作,因为此写入操作可能会导致二进制树缓慢而完全的重新平衡,即长写入操作期间的快速读取操作将返回错误的结果。
- 全局变量 多读取器 一个写入器多线程安全?
- boost::文件系统::recursive_directory_iterator多线程安全
- 静态 constexpr 类成员变量对多线程读取是否安全?
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 实现在多线程代码中安全恢复的断点
- 是否可以访问非线程安全容器内指针指向的值(线程安全映射中的条目)?
- 在 OpenCV 中访问具有多个线程的 Mat 是否线程安全?
- C++:一个写入器/多个读取器访问一个unordered_map线程安全
- 为多线程环境包装 c++ new/delete 的安全/好方法
- 线程安全 std::map:锁定整个映射和单个值
- 同一个ifstream可以有多个"cursors"吗?这会是线程安全的吗?
- 是多个线程渲染到单个OpenGL上下文线程安全的线程
- 多线程将映射分为多个部分
- C++多线程:是本地静态lambda线程安全的初始化
- 在 c++ 的多个线程中编写 c 数组的不同项是否线程安全
- 线程安全类占用了多个资源
- 在多线程程序中使用动态数组的头段安全吗
- 如何在不使用的情况下在 <mutex>C++11 中实现多线程安全单例
- 为什么映射在C++中不是多线程安全的
- C++多线程安全局部变量