【问题标题】:Iterating through an STL map with an iterator by different threads不同线程使用迭代器迭代 STL 映射
【发布时间】:2013-09-25 09:22:09
【问题描述】:

我有一个将由两个线程访问的 STL 映射。 它们都不插入也不删除元素:它们只是读取。

如果它只是一个简单的数组,我相信这不会造成麻烦。 但是,STL 映射是一个复杂的数据结构,我不知道它的实现。 这会导致数据竞争吗?

【问题讨论】:

标签: c++ multithreading stl synchronization


【解决方案1】:

标准 C++ 容器(截至 2011 年)允许多个并发读取器安全访问(即通过 const 成员函数)。

也就是说,您没问题(假设您与容器一起使用的类型上的 const 成员函数遵循相同的规则:按位-const 除外,对象不受其他线程访问的保护)。

如果您使用的是旧实现,理论上您可能会遇到问题,但我对此表示怀疑。

这是标准 (N3337) 的库介绍部分的全部内容。我认为仅凭这些段落中的任何一段都不足以回答您的问题,因此您得到了全部!

17.6.5.9 避免数据竞争[res.on.data.races]

1 本节规定了实现应满足的要求,以防止数据 比赛(1.10)。每个标准库函数都应满足每个 要求,除非另有规定。实施可能会阻止 除了下面指定的情况之外的数据竞争。

2 C++ 标准 库函数不得直接或间接访问对象 (1.10) 可由当前线程以外的线程访问,除非 通过函数的直接或间接访问对象 论据,包括这个。

3 C++ 标准库函数不应 直接或间接修改线程可访问的对象(1.10) 除了当前线程之外,除非直接访问对象 或间接通过函数的非常量参数,包括 this。

4 [注意:例如,这意味着实现不能使用 用于内部目的的静态对象,无需同步,因为它 即使在未明确共享的程序中也可能导致数据竞争 线程之间的对象。 ——尾注]

5 一个 C++ 标准库函数 不应访问通过其参数间接访问的对象或 通过其容器参数的元素,除了调用函数 其对这些容器元素的规范所要求的。

6 调用标准库得到的迭代器的操作 容器或字符串成员函数可以访问底层 容器,但不得对其进行修改。 [注:特别是容器 使迭代器无效的操作与 与该容器关联的迭代器。 ——尾注]

7 实现可以在线程之间共享它们自己的内部对象 如果对象对用户不可见并且受到数据保护 比赛。

8 除非另有说明,C++ 标准库函数 应仅在当前线程内执行所有操作,如果那些 操作具有对用户可见的效果 (1.10)。

9 [注意:如果没有可见的副作用,这允许实现并行化操作。 ——尾注]

【讨论】:

  • 只要只使用 const 成员,并且值遵循相同(const 成员不能在位级别更改任何内容;唯一例外:像 @987654329 这样的线程原语@)
  • 根据cplusplus.com/reference/map/map/begin,begin 有不同的版本:(1) iterator begin() (2) const_iterator begin() const: 我的问题是“我怎么知道会使用哪一个” ?
  • @takwing 如果你有一个const 对象,你会得到const 版本。但是,如果您明确知道您想要const_iterators 并且不关心您的上下文中mapconstness,请使用cbegincend 成员函数。
  • @BoBTFish,通过 const 对象,是否意味着 条目中的值是 const 类型?
  • @takwing 我的意思是如果map 本身是const,那么myMap.begin() 将返回const_iteratormap 可能是 const 出于各种原因,包括:1)它是这样声明的:const std::map<int, int> myMap;(有限使用)。 2) 它作为const 类实例的成员访问:const MyClass myInstance; myInstance.mapMember_.begin();。 3)你在const成员函数中访问某个类的成员(这基本上是2):void myClass::foo() const { mapMember_.begin(); }
猜你喜欢
  • 2011-04-02
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
相关资源
最近更新 更多