std :: map的高效线程同步技术

时间:2013-08-30 10:30:34

标签: c++ multithreading dictionary std stdmap

我正在std::map< StudentName, Marks > StudentNamestd::stringMarks为整数。

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

  1. 查找StudentName。如果存在,请增加其Marks
  2. 降低Marks的{​​{1}}。
  3. StudentName添加到地图中。
  4. 从地图中删除StudentName
  5. 问题:在多线程环境中对StudentName执行上述操作的最有效方法是什么?

    当前解决方案: 在地图上执行所有这些操作的代码放在关键部分中。但这会降低性能 (例如,如果某个帖子正在为某个学生添加标记,为什么其他想要为不同学生添加标记的帖子需要等待?)

    我认为可以做到这一点:
    我从SO上的其他类似问题/答案中收集了关于多线程的信息,这是我认为我需要做的事情。如果std::map不是线程安全的(即,其他线程在更新时不应访问映射)

    1. 我想只将最后两个(添加/删除StudentName)活动排除在外(在向地图添加/删除元素时,不应该并行执行其他活动)
    2. 不允许多个线程访问地图的同一元素(这样多线程不能同时尝试增加/减少同一学生的分数)
    3. 但我不知道如何实现这一目标(可以使用哪些线程同步对象/技术)我正在通过VS2010在Windows上开发此应用程序

      这里有任何建议或替代方法吗?

      更新 感谢大家的投入。不幸的是,VS2010中没有原子注入。所以,这是我打算根据你的输入做的。我有三种锁: 在地图上:map_read_lock,map_write_lock 元素:element_write_lock (对于每个元素)

      现在,

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

      添加/删除要映射的元素时:获取map_write_lock (这将阻止容器的并发更新,我相信不建议这样做)

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

3 个答案:

答案 0 :(得分:3)

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

或者,您可以在地图上使用rwlock,也可以使用独占 锁定地图中的每个元素。要修改标记,请执行 地图上的读锁定以及元素上的独占锁定;至 添加或删除一个学生,你在地图上采取写锁定。但 这需要大量额外资源。

答案 1 :(得分:0)

  • 第一个问题:学生评分的效率如何?
  • 第二个问题:真的需要多线程吗?如果它是为了效率,也许它甚至没有帮助。

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

答案 2 :(得分:0)

  
      
  1. 我想只将最后两个(添加/删除StudentName)活动排除在外(在向地图添加/删除元素时,不应该并行执行其他活动)
  2.   

为此,您需要在地图上锁定读写器。

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

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

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

因此并行访问多个单独的元素。

Mark的特定情况下,您还可以查看std::atomic。当一个简单的atomic可以做你想做的事情时,无需使用锁定。)