C++ 中的标准输出流是线程安全的(cout、cerr、clog)吗?

Posted

技术标签:

【中文标题】C++ 中的标准输出流是线程安全的(cout、cerr、clog)吗?【英文标题】:Are standard output streams in C++ thread-safe (cout, cerr, clog)? 【发布时间】:2010-12-01 18:56:03 【问题描述】:

我知道目前C++没有线程的概念,但是this article is saying:

类型安全、线程安全、可移植 日志记录机制

.....

fprintf() 函数是线程安全的, 所以即使这个日志是从 不同的线程,输出线 不会乱码。

coutcerrclog 呢?

我认为这个问题也适用于 C++ 中的所有类型的流类型,例如 fstreamstringstream

【问题讨论】:

Note: the answer is now "yes", in C++11. @GManNickG:我使用 Visual Studio 2013 C++,但 cout 仍然不是线程安全的。屏幕上的输出大多已损坏/混合。 @MehmetFide:线程安全不同于同步(混合/交错字符串); C++11 标准保证,在使用来自不同线程的这些对象时,实现不会导致数据竞争,而您可以确保多个 operator<< 调用是同步的。 【参考方案1】:

这篇文章对fprintf API 的POSIX 标准提出了声明。它没有说明 C++ 流。这是完全正确的,因为这些流上没有这样的保证。

请注意,尽管该文章中的日志记录类使用 C++ 流语法,但它通过为每个日志记录事件创建和销毁的 std::ostringstream 对象来执行此操作,因此不会在线程之间共享。它使用fprintf 将内容实际写入控制台。

Microsoft C 库声称与 POSIX 兼容,因此本文中的代码可能具有相当广泛的可移植性(因为许多其他流行的操作系统都与 POSIX 兼容)。但这并不意味着标准 C++ 流是线程安全的。

【讨论】:

【参考方案2】:

这将是特定于实现的细节。您可以询问具有运行时库 Y 的编译器 X 是否具有线程安全的标准流,但您不能询问是否所有实现都有,因为允许实现在线程安全方面有所不同。这是 C++ 没有内置线程概念的部分含义。它是所有特定于实现的。

【讨论】:

我也是这么想的 :) 但是文章声称代码也是可移植的! 我猜这篇文章的作者只是说它在他尝试过的任何地方都有效。他可能没有尝试过,比如 Keil C 和 HomeGrownRTOS v1.2,或任何其他不常见的组合。 这篇文章不是在讨论 C++ 流。 @Warren Young - 文章的作者并不是那么愚蠢,事实上。他们特别说明了他们的代码必须支持什么标准才能工作。 @Earwicker,我认为这与是否愚蠢无关。作者声称它是可移植的 posix 代码。纯 C 函数 fprintf 仍然不是线程安全的。【参考方案3】:

由于当前的 C++ 标准甚至不承认存在称为“线程”的东西,因此它当然根本没有提供任何关于线程安全的保证。

这都是实现定义的。

【讨论】:

以上是关于C++ 中的标准输出流是线程安全的(cout、cerr、clog)吗?的主要内容,如果未能解决你的问题,请参考以下文章

IO流在C++中的应用

c++语言中的标准输入输出用cin和cout表示,请问名字中的'c'表示啥?

c++中scanf和cout有啥区别

c++中的cin 和cout 有啥用怎么用 >> <<有啥用怎么用

C/C++编程笔记:C++中的标准输入流 & 标准输出流

流与缓冲区的理解