12

我在这里读了很多帖子的问题,如果 C++ 的标准容器(如“list”或“map”是线程安全的,并且所有人都说它不是一般情况。并行读取应该没问题,但并行写入或并行读取和写入可能会导致问题。

现在我在www.cplusplus.com发现在大多数操作期间访问或修改列表是安全的。

一些例子:

地图::查找

访问容器(const 和非 const 版本都不会修改容器)。不访问映射值:同时访问或修改元素是安全的。

地图::插入

容器被修改。并发访问现有元素是安全的,尽管容器中的迭代范围不是。

我是否误解了 cplusplus.com 或者关于 std 容器中的线程安全还有什么我必须知道的。

提前致谢!

PS:我要的是 C++03 而不是 C++11

4

4 回答 4

13

并行读取应该没问题,但是并行写入或并行读写可能会出现问题。

这是正确的。这是对 C++ 中对象的非同步访问通常提供的保证。这样的“问题”正式称为数据竞争

现在我在 www.cplusplus.com 发现在大多数操作期间访问或修改列表是安全的。

不,容器提供的不仅仅是并发读取的基本保证。如果一个线程访问它而另一个线程修改它,则会出现数据竞争。但是,对于某些容器,有时在修改容器本身时访问容器的元素是安全的。

第一个例子是说不find修改容器或访问元素(只有键),所以如果其他线程正在访问它,或者修改(不同的)值而不修改容器本身是安全的。

第二个示例是说您可以安全地访问现有元素(使用对该元素的引用或迭代器),因为插入元素不会干扰现有元素。

我要的是 C++ 而不是 C++11

如今,C++C++11。如果您要询问该语言的历史版本,他们对线程无话可说,因此该问题通常无法回答,仅针对特定的实现和线程框架。

于 2013-09-06T12:03:57.500 回答
6

听起来差不多。

请注意map,如果您修改实际值,则从多个线程中访问值也需要受到保护。如果您知道两个线程更新不同的条目(我不是指插入/删除),那么它是安全的。

于 2013-09-06T11:57:25.260 回答
2

在 C++11 之前,标准中没有“线程”的概念。因此,容器是否是线程安全的问题在 C++03 的上下文中是没有意义的。

于 2013-09-06T11:56:04.290 回答
0

正如 Marcin 所指出的,C++03 没有线程的概念。因此,即使在写入完全完成后在两个线程中并发读取,您也不能假设任何线程安全操作。

考虑这种情况:在 t=0 时,您创建一个线程,让我们调用 A 在 t=10 秒时,线程 B(在线程 A 被创建之前存在)写入容器。在 t=1 小时,线程 A 和 B 都尝试通过 3rd 方库(例如 pthread)在没有任何同步的情况下读取容器。

C++03 只保证线程 B 会看到正确的值。但是并不能保证线程 A 会看到正确的值,因为 C++03 期望每个程序都是单线程的,因此 C++03 规范只能保证事件序列在编程顺序中可见(就像在 1线)。

于 2013-09-06T13:35:33.350 回答