繁体   English   中英

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

[英]std::cout is thread safe, but can cause race conditions?

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

在此处输入图像描述

如果std::cout可以有竞争条件,那么它是线程安全的吗? 根据定义,线程安全不是没有竞争条件吗?

它区分了对operator<<的调用顺序和作为这些调用结果的每个字符的输出。

具体来说,每个字符的线程之间没有冲突,但是,如果你有两个线程 output paxdiablo ,你可能会得到任何一个(以及其他):

paxdiablo
diablopax
pdaixablo
padiablox
diapaxblo

您引用的文字说明的是,(例如) pd的 output 不会混合,这会导致数据竞争。

竞争条件不一定是问题,也不一定是线程安全问题,它只是意味着行为可能会因顺序而异。 如果任意排序可能会以某种方式损坏数据,则可能会成为这样的问题,但此处并非如此(除非您认为格式错误的 output 已损坏)。


它类似于声明:

result = a * 7 + b * 4;

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


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

线程安全有很多级别。 有些程序每次都必须以完全相同的顺序完成。 它们必须就像在单个线程中执行一样。 其他允许在执行语句的顺序上具有一定程度的灵活性。 规范关于std::cout state 的声明属于后者。 未指定字符打印到屏幕的顺序。

您可以在编译过程中看到这两种行为。 在大多数情况下,我们不关心编译的顺序。我们愉快地键入make -j8并有 8 个线程(进程)并行编译。 无论线程做什么工作对我们来说都很好。 另一方面,考虑NixOS的编译要求。 在该发行版中,您自己编译每个应用程序,并与作者发布的哈希值进行交叉检查。 在 NixOS 上编译时,在一个编译单元(一个.c 或.cpp)内,您绝对必须像有一个线程一样操作,因为您每次都需要完全相同的产品。

这种竞争行为有一个更黑暗的版本,称为“数据竞争”。 这是当两个写入器尝试同时写入同一个变量,或者读取器尝试读取它而写入器尝试写入它时,所有这些都没有任何同步。 这是未定义的行为。 的确, 我最喜欢的编程页面之一煞费苦心地介绍了如果有数据速率可能会出错的所有事情。

那么规范中关于需要锁定 cout 的内容是什么? 它的意思是指定了线程间行为,并且没有数据竞争。 因此,您不需要保护 output stream。

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

那里的文字警告您,完全用“线程安全”组件构建某些东西并不能保证您构建的东西将是“线程安全的”。

std::cout stream 被称为“线程安全”,因为在没有任何其他同步的情况下在多个线程中使用它不会破坏其任何底层机制。 cout stream 将以可预测、合理的方式运行; 各种线程写的所有东西都会出现在output中,不会出现不是某个线程写的东西,任何一个线程写的所有东西都会按照一个线程写的顺序出现,等等。而且,它不会抛出意外的异常,或程序段错误,或覆盖随机变量。

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

不要忘记这样的语句不是一个std::cout function 调用; 这是三个单独的电话。

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

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

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

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

I like there are 5 fido doodles here.
.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM