【问题标题】:Which STL container has a thread-safe insertion process?哪个 STL 容器具有线程安全的插入过程?
【发布时间】:2011-12-17 21:40:56
【问题描述】:

哪个 STL 容器具有线程安全的插入过程?我希望多个线程同时插入同一个容器中。欢迎使用除 STL(即 Boost)以外的任何实现!

【问题讨论】:

  • 您在寻找什么样的容器?什么平台要求?哪个 C++ 版本? 98 还是 11?
  • OP 指定这是关于 linux 的,但由于它可能会出现在像我这样搜索“C++11 线程安全容器”的人身上,这个关于 Visual-C++ 扩展的答案可能很有用: stackoverflow.com/a/7817526/197229

标签: c++ data-structures stl thread-safety


【解决方案1】:

STL 容器不是线程安全的。如果你愿意的话,你必须通过你自己的同步来强加它。

【讨论】:

  • 我试图避开多线程中的临界区,因为它会降低性能!
  • 不管你想做什么:库仍然不是线程安全的,除非你的实现另有说明。
  • @Tarek 即使容器本身是“线程安全的”,它也不会神奇地为您提供跨线程同步。例如,即使内部“插入”不会导致跨线程损坏,但如果另一个线程有一个开放的迭代器,它可能会变得无效,而无法预测它。您需要实现自己的锁。
  • @Tarek:您希望如何在没有锁的容器中实现同步?有无锁数据结构,但通常并不常见,您必须找到一个这样的库并根据它们提供的内容调整您的算法。
  • @Voo value 语义的语言和 reference 语义的语言之间存在巨大差异,特别是除非您包含的所有元素都提供只有原子操作,您不能提供无锁容器来保存它们,因为无论容器操作有多好,在 value 语言中插入意味着 复制 值,就像读取该值,如果该值可以删除,则无法以无锁方式执行。这正是我提到您需要调整算法(程序)的原因。
【解决方案2】:

容器遵循 KISS 原则(保持简单),因此不具备同步功能。大多数情况下,这种假设的嵌入式同步是不够的,因为大多数情况下,对某些其他对象的访问必须与对容器的访问同步。将您的容器与一把锁结合起来,就是这样。

【讨论】:

    【解决方案3】:

    标准不要求任何 STL 容器是线程安全的。一个实现可能是线程安全的,尽管我不确定他们如何使用当前的 API 实现它;并且更改 API 将使它们不再与标准兼容。

    如果 LGPL 是可接受的,Intel TBB 有线程安全容器(这些容器在内部使用锁,这确实会影响它们的性能)。

    【讨论】:

    • 我可以在我不是管理员的计算机上安装和使用 TBB 吗?
    • TBB 是一个常规库。即使您不是管理员,您也应该能够构建和链接到库,但是您必须将库与您的应用程序放在同一个文件夹中,并且您将无法轻松地在多个程序之间共享库.
    【解决方案4】:

    我试图避免多线程中的关键区域,因为它会降低性能!

    相反,它提高了性能。因为容器类可以做的锁定类型只是非常细粒度的类型,必须为每个简单的操作获取锁。这太贵了。当您处理锁定时,您可以奢侈地获取锁定并执行许多操作。这不会提高并发的几率,但会大大减少锁定开销。您可以选择对您的应用最有意义的策略,而不是强加于您。

    此外,几乎不可能编写一个既不容易死锁也不会非常昂贵的线程安全容器实现。迭代器是问题所在。库编写者必须选择在迭代器的生命周期内锁定(有死锁的风险),或者在另一个线程更改集合时需要更新所有活动的迭代器(昂贵)。只有昂贵的选择是安全的。同样,您选择最有意义的策略,不会强迫您做出昂贵的选择。

    【讨论】:

    • 有时无锁并发容器更好。否则它们将不存在。
    【解决方案5】:

    既然您说欢迎任何其他(非 STL)实现,我建议使用英特尔的线程构建模块。它们具有线程安全的并发容器,具有非常好的性能特征。

    【讨论】:

      【解决方案6】:

      看看 Boost.Lockfree (http://www.boost.org/doc/libs/1_53_0/doc/html/lockfree.html)。它提供以下线程安全的实现:

      boost::lockfree::queue
        a lock-free multi-produced/multi-consumer queue
      boost::lockfree::stack
        a lock-free multi-produced/multi-consumer stack
      boost::lockfree::spsc_queue
        a wait-free single-producer/single-consumer queue (commonly known as ringbuffer)
      

      【讨论】:

        猜你喜欢
        • 2012-10-07
        • 2017-02-01
        • 1970-01-01
        • 2016-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多