std :: vector或boost :: vector线程安全吗?

时间:2012-01-28 02:59:28

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

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

3 个答案:

答案 0 :(得分:52)

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

  1. 同一个容器可以有多个并发读者
  2. 如果有一位作家,就不会有作家和读者
  3. 这些通常不是人们想要的线程安全保证,但鉴于标准容器的接口非常合理:它们旨在在没有多个访问线程的情况下有效使用。为他们的方法添加任何类型的锁定都会干扰这一点。除此之外,容器的接口对于任何形式的内部锁定都不是很有用:通常使用多种方法,访问取决于先前访问的结果。例如,在检查容器不是empty()之后,可能会访问某个元素。但是,使用内部锁定时,无法保证在实际访问对象时对象仍在容器中。

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

    保证和要求见17.6.4.10 [res.on.objects]第1段:

      

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

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

答案 1 :(得分:27)

  

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

不安全

  

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

  

我想避免做额外的“锁定和释放”工作,因为我是图书馆用户而不是图书馆设计师。我希望为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.

答案 2 :(得分:9)

  

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

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