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

52

我有多个线程同时调用共享对象的std::vectorpush_back()方法。 std::vector是线程安全的吗?还是我需要自己实现机制来使其线程安全?
我希望避免做额外的“锁定和释放”工作,因为我是库的用户而不是库的设计者。我希望寻找现有的线程安全解决方案来处理向量。 boost::vector如何呢?它是从boost 1.48.0开始新引入的。它是线程安全的吗?


3
这一定是一个重复的问题。但是,标准容器中没有一个是线程安全的。 - smparkes
参见:https://dev59.com/R3I-5IYBdhLWcg3wI0x9 - ergosys
不完全是重复,但相关:https://dev59.com/snNA5IYBdhLWcg3wEpkU - ergosys
1
这个链接下的“线程安全”部分应该包含你所需的所有信息:https://en.cppreference.com/w/cpp/container。 - Franzi
3个回答

64
C++标准为标准C++库中所有类提供了某些线程保障。这些保障可能不是您预期的,但对于所有标准C++库类都提供了某些线程安全保证。请确保阅读所做出的保证,因为标准C++容器的线程保证通常与您期望的不一样。对于某些类别,通常会提供不同(通常更强)的保证,下面的答案特别适用于容器。容器基本上具有以下线程安全保证:
  1. 可以同时存在多个读取同一容器的并发操作
  2. 如果有一个写入操作,就不应再有其他写入操作和读取操作
这些通常不是人们希望得到的线程安全保证,但考虑到标准容器的接口,这些是非常合理的:它们旨在在没有多个访问线程的情况下高效使用。为其方法添加任何形式的锁定将干扰此过程。除此之外,容器的接口对于任何形式的内部锁定都不是真正有用的:通常会使用多个方法,并且访问取决于先前访问的结果。例如,在检查容器不是空的(`empty()`)后,可能会访问元素。但是,使用内部锁定不能保证在实际访问时仍然存在对象。
为满足提供上述保障的要求,您可能需要为同时访问的容器使用某种形式的外部锁定。我不清楚boost容器是否具有与标准容器类似的接口,但如果是,则会怀疑它们具有完全相同的保障。
这些保障和要求在17.6.4.10 [res.on.objects]第1段中给出:

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

...和17.6.5.9 [res.on.data.races]。本节基本上详细说明了非正式描述中的内容。


2
如果它只是函数,那么它就会是可重入的。但是,涉及到的对象保证不会被读取操作修改。此外,可重入性是指在单线程程序中递归调用的特性。 - Dietmar Kühl
“读者”和“写者”是指容器的结构,而不是对其中对象的写入,对吗?例如,同时向3个不同的向量元素进行写入,并从另外10个线程中的第四个进行读取,只要没有插入或删除元素,就可以允许这样做。迭代器有效性规则在这里似乎很相关。 - Ben Voigt

38

我有多个线程同时调用一个 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.

12
我有多个线程同时在共享的std::vector对象上调用push_back()。... 我希望寻找现有的线程安全解决方案来处理向量。
请查看Intel's TBB中的concurrent_vector。严格来说,它在内部与std::vector有很大不同,并且其API不完全兼容,但仍然可能适用。您可以在TBB开发人员的博客中找到一些有关其设计和功能的详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接