2

我在std::map< StudentName, Marks >哪里和StudentNamestd::stringMarksis 一个整数。

现在,在我的应用程序中,多个线程正在访问此映射以:

  1. 找到StudentName。如果存在,增加它的Marks.
  2. 的减少MarksStudentName
  3. 添加StudentName到地图。
  4. StudentName从地图中删除。

问题:std::map在多线程环境中执行上述操作的最有效方法是什么?

当前解决方案: 在地图上执行所有这些操作的代码放在临界区中。但这会降低性能。
(例如,如果一个线程正在为特定学生添加分数,为什么其他要为不同学生添加分数的线程需要等待?)

这是我认为可以做到的:
我从 SO 上的其他类似问题/答案中收集了关于地图上多线程的信息,这就是我认为我需要做的。提供std::map不是线程安全的,(即更新时没有其他线程应该访问映射)

  1. 我只想将最后两个(添加/删除 StudentName)活动排他性(在向地图添加/删除元素时不应并行执行其他活动)
  2. 不允许多个线程访问同一个 map 元素(这样多个线程不能同时尝试增加/减少同一个学生的分数)

但我不确定如何实现这一点(可以使用哪些线程同步对象/技术)我正在通过 VS2010 在 Windows 上开发此应用程序

请问这里有什么建议或替代方法吗?

更新: 感谢大家的意见。不幸的是,VS2010 中没有可用的原子整数。所以,这就是我计划根据你的意见做的事情。我将拥有三种锁: 在地图上:map_read_lock、map_write_lock 在元素上:element_write_lock(对于每个元素)

现在,

在地图中查找元素时:获取 map_read_lock (这将允许我同时查找)

向地图添加/删除元素时:获取map_write_lock (这将防止容器的并发更新,我认为不推荐)

更改值时:Get (map_read_lock & element_write_lock) (这将允许并行更改不同的值,但会阻止同时更改相同的值。此外,将防止在更新容器时更改值,反之亦然)

4

3 回答 3

3

当一个线程增加学生 A 的分数,而另一个线程删除学生 A 时会发生什么?即使只是修改标记,您也需要锁定地图。或者您需要更复杂的事务管理(对于这种简单的情况可能不合理)。

或者,您可以在地图上使用 rwlock,并在地图中的每个元素上使用排他锁。要修改标记,您需要在地图上设置读锁,并在元素上设置排他锁;要添加或删除学生,您需要在地图上设置写锁。但这需要大量的额外资源。

于 2013-08-30T11:00:51.190 回答
0
  • 第一个问题:给学生评分的效率应该如何?
  • 第二个问题:真的需要多线程吗?如果是为了效率,也许它甚至没有帮助。

之后,您可以考虑Reader/Writer lock,其中 Reader lock 不是独占的。但请注意,因为实际评分是写作,所以您可能需要为每个学生设置另一个锁以避免争用。

于 2013-08-30T10:59:23.983 回答
0
  1. 我只想将最后两个(添加/删除 StudentName)活动排他性(在向地图添加/删除元素时不应并行执行其他活动)

为此,您需要在地图上设置读/写锁。

  • 添加/删除需要独占访问(作者)
  • 访问学生需要(仅)共享访问(读者)
  1. 不允许多个线程访问同一个 map 元素(这样多个线程不能同时尝试增加/减少同一个学生的分数)

这也是相对简单的:地图的每个元素都应该有自己的锁。这样,在不修改地图结构的情况下访问元素时,您可以:

  • 将地图锁定为共享访问
  • 锁定单个元素(即每个元素都需要自己的锁定)

从而并行访问多个单独的元素。

在您的特定情况下Mark,您也可以查看std::atomic. atomic当一个简单的人可以做你想做的事时,不需要去使用锁:)

于 2013-08-30T14:38:29.917 回答