std :: cout是线程安全的,但是会导致竞争状况吗?

问题描述

我正在查看有关C ++多线程的在线课程,并且看到以下内容:

enter image description here

如果std::cout可以具有竞争条件,那么它的线程安全性如何?顾名思义,线程安全难道没有竞争条件吗?

解决方法

它区分了对operator<<的调用顺序和由于这些调用而输出的每个字符

具体来说,每个字符之间的线程之间没有冲突,但是,如果分别有两个线程输出paxdiablo,则可能会导致(以及其他任何一个):

paxdiablo
diablopax
pdaixablo
padiablox
diapaxblo

您引用的文字说明的是,pd的输出不会混合在一起,这会引起数据争用。

竞争条件不是不必要的问题,也不是线程安全的问题,它仅表示行为可以根据顺序而变化。如果任意排序会以某种方式破坏数据,则可能会出现这样的问题,但事实并非如此(除非您认为格式错误的输出会被破坏)。


类似于以下语句:

result = a * 7 + b * 4;

ISO C ++实际上并没有强制要求a * 7b * 4的求值顺序,因此您可以考虑竞争条件(这很合理,尽管不太可能,可以将各个计算移交给单独的CPU以实现并行性),但这绝不是问题。


有趣的是,ISO C ++没有提到竞争条件(可能会成为问题),而只提到了数据竞争(肯定​​是一个问题)。

> ,

线程安全有很多级别。某些程序每次必须以完全相同的顺序完成。如果它们是在单个线程中执行的,则它们必须为准。其他允许在执行语句的顺序上有一定程度的灵活性。规范中关于std::cout的声明指出,它属于后一类。未指定字符在屏幕上的打印顺序。

您可以在编译操作中看到两种行为。在大多数情况下,我们并不关心编译的顺序。我们很高兴地键入make -j8并有8个线程(进程)并行编译。无论执行什么线程,我们都可以。另一方面,请考虑NixOS的编译要求。在该发行版中,您可以自己编译每个应用程序,并根据作者发布的哈希值对其进行交叉检查。在NixOS上进行编译时,在一个编译单元(一个.c或.cpp)中,如果有一个线程,您绝对必须操作,因为每次都需要确定的确切产品。

存在这种竞争行为的较暗版本,称为“数据竞争”。在这种情况下,两个编写者试图同时编写同一个变量,或者当一个编写者试图写入该变量时,一个读者试图读取它,而这一切都没有任何同步。这是未定义的行为。确实,one of my favorite pages on programming精心研究了如果存在数据速率可能会出错的所有情况。

那么关于需要锁定cout的规范怎么说?它的意思是指定了线程间行为,并且没有数据争用。因此,您不需要保护输出流。

通常,如果您想保护它,现在是退后一步并评估您的选择的好时机。当然,您可以在cout的用法上放置一个互斥体,但不能在正在使用的任何库上放置它,因此,如果它们打印任何内容,则在交织方面仍然会遇到问题。现在是查看输出系统的好时机。您可能要开始将消息传递到集中式池(受互斥锁保护),并使用一个线程将消息写出到屏幕上。

,

此处的文字警告您,完全用“线程安全”的组件来构建某些内容并不能保证您构建的内容将是“线程安全的”。

std::cout流被称为“线程安全”的,因为在多个线程中使用它而没有任何其他同步不会破坏其任何基础机制。 cout流将以可预测的合理方式运行;各个线程写入的所有内容都将出现在输出中,没有任何线程未写入的内容将显示,任何 one 线程写入的所有内容的出现顺序与 one 线程编写了它,等等。此外,它不会引发意外的异常,不会对您的程序进行段错误或覆盖随机变量。

但是,如果您的程序允许多个线程“竞争”以编写std::cout,那么库的作者将无法做任何事情来帮助预测哪个线程将获胜。如果您希望看到由多个线程编写的数据以某种特定顺序出现,那么确保这些线程以相同的顺序调用库是您的责任。

不要忘记这样的语句不是 one std::cout函数调用;这是三个单独调用。

std::cout << "there are " << number_of_doodles << " doodles here.\n";

如果其他某个线程同时执行此语句(也执行三个调用):

std::cout << "I like " << name_of_favorite_pet << ".\n";

然后可以交错六个单独的std::cout调用的输出,例如:

I like there are 5 fido doodles here.
.

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...