为啥 C++ STL 不提供一组线程安全的容器? [复制]

Posted

技术标签:

【中文标题】为啥 C++ STL 不提供一组线程安全的容器? [复制]【英文标题】:Why does the C++ STL not provide a set of thread-safe containers? [duplicate]为什么 C++ STL 不提供一组线程安全的容器? [复制] 【发布时间】:2012-02-14 09:12:49 【问题描述】:

可能重复:question about STL thread-safe and STL debugging

我目前正在从事一个使用 C++ 开发的项目。最近我们正在考虑用一些等效的 STL 替换一些自定义的线程安全容器,以提高效率。

但是看了一会,发现STL中根本没有提供线程安全的容器,这让我很惊讶。有什么原因吗?

【问题讨论】:

线程在 0x 之前甚至还不是 C++ 的一部分。因此没有容器。 非正式地,在大多数实现中operator new 是线程安全的。因此,至少可以保证该部分在 STL 中是线程安全的。另外,所有的 STL 容器都有一个template 参数用于分配(一般为std::allocator),您可以随时提供自己的线程安全分配方法。 【参考方案1】:

可能是因为它实际上并没有那么有用(除了@Luchian Grigore 在另一个答案中所说的)。即使个别容器操作是线程安全的,你仍然需要做很多工作来确保线程安全。例如,即使容器本身是线程安全的,这个简单的代码也包含竞争条件:

if (!container.empty())
    container.pop();

【讨论】:

线程安全的容器会提供blocking_poppop_if_not_empty【参考方案2】:

标准库容器确实提供了一些基本的线程安全性,对于标准库容器的设计者来说,性能是一个比安全性更重要的设计目标。

所有标准库容器保证: 来自同一个容器的多个并发读取是安全的,但是 如果至少有一个编写者线程,则没有线程安全性,并且不应有任何其他编写者或阅读者。

标准库容器主要设计用于在单线程环境中高效工作,仅提供基本线程安全是确保不需要并发访问的容器的完整性能的一种方式。

基本的线程安全需要用户需要某种同步方法来通过使用互斥锁或锁来避免竞争条件。锁定或其他形式的同步通常很昂贵,因此在不必要时需要避免。

此外,鉴于标准库容器公开的接口,如果预期用途是多用途,容器的客户端或用户很容易通过使用锁定获取和释放包装底层容器操作来提供必要的锁定。线程环境。


请注意,所有实现都符合 C++ 标准规定的以下要求:

17.6.3.10 共享对象和库 [res.on.objects]

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

【讨论】:

【参考方案3】:

因为线程安全高度依赖于平台和编译器。

【讨论】:

为什么以及如何阻止标准强加线程安全要求?实现的责任是遵守他们发布的每个平台的标准指定要求。【参考方案4】:

C++ STL 提供了几乎所有其他东西都提供的那种线程安全性:您可以安全地使用来自多个线程的 STL 容器,只要一个对象不在一个线程中访问,而另一个线程正在或可能是,修改它。

【讨论】:

【参考方案5】:

一句话——因为它很难。

因为线程安全容器需要特定的设计 - 例如他们必须是persistent data structures。这样的容器最容易在功能/垃圾收集/基于事件的环境中实现。哪个 C++ 不是。

也就是说,实现这些仍然需要用户处理所有资源分配/释放。这样就违背了收藏的意义。

【讨论】:

以上是关于为啥 C++ STL 不提供一组线程安全的容器? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL容器如何解决线程安全的问题?

C++ STL容器如何解决线程安全的问题?

C++ STL容器如何解决线程安全的问题?

C++ STL容器如何解决线程安全的问题?

C++ STL容器如何解决线程安全的问题?

C++ STL 相关 部分笔记