【问题标题】:Is std::vector or boost::vector thread safe?std::vector 或 boost::vector 线程安全吗?
【发布时间】:2012-02-20 23:45:20
【问题描述】:

我有多个线程同时在std::vector 的共享对象上调用push_back()std::vector 线程安全吗?还是我需要自己实现该机制以使其线程安全?
我想避免做额外的“锁定和释放”工作,因为我是图书馆用户而不是图书馆设计师。我希望为vector寻找现有的线程安全解决方案。 boost::vector 怎么样,它是从 boost1.48.0 开始新引入的。它是线程安全的吗?

【问题讨论】:

标签: c++ boost stl thread-safety std


【解决方案1】:

C++ 标准为标准 C++ 库中的所有类提供一定的线程保证。这些保证可能不是您所期望的,但对于所有标准 C++ 库类,都做出了某些线程安全保证。但是,请确保您阅读了所做的保证,因为标准 C++ 容器的线程保证通常与您希望它们的内容不一致。对于某些不同的、通常更强的类,我们会做出保证,下面的答案特别适用于容器。容器本质上具有以下线程安全保证:

  1. 同一容器可以有多个并发读取器
  2. 如果只有一个作者,就没有更多的作者和没有读者了

这些通常不是人们想要的线程安全保证,但考虑到标准容器的接口,它们是非常合理的:它们旨在在没有多个访问线程的情况下有效使用。为他们的方法添加任何类型的锁定都会干扰这一点。除此之外,容器的接口对于任何形式的内部锁定都没有真正的用处:通常会使用多种方法,并且访问取决于先前访问的结果。例如,在检查容器不是empty() 之后,可能会访问一个元素。但是,使用内部锁定并不能保证对象在实际访问时仍然在容器中。

为了满足提供上述保证的要求,您可能必须对并发访问的容器使用某种形式的外部锁定。我不知道 boost 容器,但如果它们的接口类似于标准容器的接口,我会怀疑它们具有完全相同的保证。

保证和要求在 17.6.4.10 [res.on.objects] 第 1 段中给出:

如果从不同线程调用标准库函数可能会引入数据竞争,则程序的行为是未定义的。 17.6.5.9 规定了可能发生这种情况的条件。 [注意:修改在线程之间共享的标准库类型的对象有未定义行为的风险,除非该类型的对象被明确指定为可共享而没有数据争用或用户提供锁定机制。 ——尾注]

... 和 17.6.5.9 [res.on.data.races]。本节主要详细介绍了 not 中更非正式的描述。

【讨论】:

  • 如果它只是功能,它会reentrancy。但是,有些对象保证不会被读取操作修改。另外,可重入性是指在单线程程序中可以递归调用的特性。
  • 通过“reader”和“writer”,你说的是容器的结构,而不是写入里面的对象,对吗?例如,可以同时写入 3 个不同的向量元素,并从另外十个线程中读取第四个元素,只要没有插入或删除元素。迭代器有效性规则似乎与此处相关。
【解决方案2】:

我有多个线程同时在 std::vector 的共享对象上调用 push_back()。 std::vector 线程安全吗?

这是不安全

或者我是否需要自己实现该机制以使其线程安全?

是的。

我想避免做额外的“锁定和释放”工作,因为我是图书馆用户而不是图书馆设计师。我希望为vector寻找现有的线程安全解决方案。

好吧,vector 的界面并不是最适合并发使用的。如果客户端可以访问锁,那很好,但是对于接口而言,可以为每个操作抽象锁定 - 不。事实上,vector 的接口在没有外部锁的情况下无法保证线程安全(假设您需要的操作也会发生变异)。

boost::vector 怎么样,它是从 boost 1.48.0 开始新引入的。它是线程安全的吗?

文档状态:

//! boost::container::vector is similar to std::vector but it's compatible
//! with shared memory and memory mapped files.

【讨论】:

    【解决方案3】:

    我有多个线程同时在 std::vector 的共享对象上调用 push_back()。 ...我希望为vector寻找现有的线程安全解决方案。

    Intel's TBB 中查看concurrent_vector。严格来说,它在内部与std::vector 有很大不同,API 不完全兼容,但仍然可能适用。您可能会发现其设计和功能的一些细节in the blogs of TBB developers

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-07
      • 2021-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      相关资源
      最近更新 更多