C ++线程安全摘要

时间:2011-03-21 17:32:48

标签: c++ multithreading thread-safety c++11

我想根据当前标准和C ++ 0x以及实际情况(一般来说,在我的情况下使用gcc 4.5.1)总结C ++中的线程安全性。

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

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

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

4 个答案:

答案 0 :(得分:6)

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

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

这些事情在实践中不是线程安全的原因是多种多样的。通常,STL容器不是线程安全的,因为它们的每个基本更新操作都需要多个步骤来完成。如果一个线程试图读取或更新容器,而另一个线程正在更新它,那么容器将处于不确定状态,因此结果将是不可预测的。

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

答案 1 :(得分:1)

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

C ++ 0x对于线程安全/共享方面的容器没有多少谈论(根本没有?),但确实讨论了赋值等。最后,它几乎完全相同 - 即使对象在容器中,您正在读/写数据,并且必须在/如果至少一个线程可能修改数据时同步。

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

答案 2 :(得分:0)

POD和标准定义的类型没有任何线程安全性。完全取决于代码用户同步他们的线程以确保不会发生任何不良事件。

在C ++ 0x中,我不知道;没有真正检查标准的那个区域。

答案 3 :(得分:0)

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

各种专有线程库(例如Solaris线程)由供应商生成,业界最终​​在pthread库上标准化,最初使用纯粹的用户空间线程模型(阻塞I / O之类的调用会阻塞所有线程)以及后来的内核线程支持。 Windows,OS / 2和各种其他操作系统提供专有的线程设施。

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

尽管存在跨平台的线程库,但最终的影响是线程往往是特定于平台的。