2011-03-21 118 views
5

我想根据当前的标准和C++ 0x以及实际情况(通常来说,但在我的情况下使用gcc 4.5.1 )。C++线程安全摘要

对于STL容器,我的理解是,根据当前标准,不保证线程安全性。这是真的,但实际上它们对于单个作者,多读者使用(在gcc和可能是最现代的编译器)是线程安全的?这是由C++ 11保证的吗?

POD类型呢?我知道这个标准没有任何保证,但我被告知,在实践中,所有人都是线程安全的阅读和写作。当然,即使像增量运算符这样简单的东西可能仍然需要同步,因为可能有多个读取和写入。

我主要对答案感兴趣,但答案背后的原因将被赞赏。

+1

在当前的C++标准中没有“线程”或“线程安全”的概念。 – 2011-03-21 17:35:01

+1

关于这种线程安全性的问题,没有任何关于“线程安全”的含义的说明基本上是不可能回答的。必读:[你称之为“线程安全”的东西是什么(http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-线程safe.aspx)。 – 2011-03-21 17:35:23

+0

@David:伟大的文章,谢谢:) – 2011-03-21 17:45:05

回答

1

目前的标准在任何方面都没有提及线程。实际上,标准容器提供线程安全读取,但需要同步写入。

关于线程安全/共享,C++ 0x并没有多少谈论(关于线程安全/共享的容器),而是谈论分配等。最后,虽然对象位于容器中,但您读取/写入数据,并且至少有一个线程可能会修改数据时必须同步,所以它的结果几乎相同。

POD数据并没有真正改变:修改需要同步作为一般规则。通常有一些数据类型的子集通常是原子操作,但该子集的成员因平台而异。它通常包括类型,直到分配“自然”对齐的硬件的本地字大小;还有其他问题可以提出更多问题。

+0

虽然C++ 0x引入了'std :: atomic',但它的名字我认为这里有一定程度的线程安全性。不是吗? – 2011-03-21 17:49:43

+0

@Matthieu M .:是的,C++ 0x在原子操作和互斥体方面增加了很多。这些将使您可以轻松地同步对容器的访问,但没有一个容器会自动同步(至少在我记得的范围内)。 – 2011-03-21 17:53:11

+0

我不认为容器是同步的。我似乎记得保证读取操作不会修改它们(这里没有Splay Tree),但这就是它。 – 2011-03-21 19:46:48

0

POD和标准定义类型没有任何线程安全性。代码用户完全可以同步他们的线程以确保没有什么不好的事情发生。

在C++ 0x中,我没有什么想法;没有真正检查标准的这个领域。

6

您提到的所有内容都不是线程安全的,无论是通过标准还是实践。

标准没有要求线程安全的原因是线程安全带来了固有成本。一般来说,C++试图不给你你没有要求的东西。如果你想要线程安全,那么你必须自己构建它。即使在包含各种同步原语的C++ 0x中也是如此。

这些东西在实际中不是线程安全的原因各不相同。通常,STL容器不是线程安全的,因为它们的每个基本更新操作都需要多个步骤才能完成。如果一个线程尝试读取或更新一个容器,而另一个线程正在更新它,则容器将处于不确定状态,因此结果将不可预知。

在POD类型的情况下,读取和写入也可以采取多个步骤来完成。这个最简单的例子是32位机器上的一个64位整数。至少需要两条指令来读取或设置值。再一次,这意味着如果一个线程在另一个线程正在更新它的过程中尝试读取或更新该值,结果将是不可预知的。

0

C语言和C++都没有在语言中内置的并发原语(例如)java与synchronised。这是(我相信)故意 - 即使是在现代版本 - 也是为了避免在不需要时的开销。 Unix在早期不支持轻量级进程,所以线程主要是内核问题。

各种专有线程库(例如Solaris线程)由供应商生产的,该行业最终标准化的pthread库,最初与纯粹的用户空间的线程模型(阻塞调用等I/O将阻止所有线程)和后面内核线程支持。 Windows,OS/2和其他各种操作系统提供专有的线程功能。

C/C++被设计为运行在可能有或没有线程支持的系统上,并且运行效率高 - 因此线程支持是可选的额外功能。 C++的设计哲学之一是程序员不应该为他们不使用的功能付费。在多核心机器的时代,人们可以争论这种方法的优点,但假设'the entire world is a PC'已被认为是现在几十年来编写可移植C代码的一个主要缺陷。

最终结果是线程往往是特定于平台的,尽管跨平台线程库确实存在。