【问题标题】:Are both calls to `fprintf(stdout, ...)` and `fprintf(stderr, ...)` guaranteed to non-interleave with multiple threads?对`fprintf(stdout, ...)`和`fprintf(stderr, ...)`的调用是否都保证与多个线程不交错?
【发布时间】:2012-10-20 13:34:09
【问题描述】:

假设我有两个线程向stderrstdout 打印一些东西(相对较长),这两个流的函数在它们永远不会“交错”字符的意义上是线程安全的吗?因此,例如,如果我有“Hello, World”,我将永远不会得到“HHellllo,, WorldWorld”或其他任何交错?这适用于 x86、GCC、Linux > 3.0。

【问题讨论】:

  • @JensGustedt:我看到了,但它没有回答 both stderrstdout 是否是线程安全的。在某处我读到stderr 不是这种情况,我需要确定一下。
  • @DervinThunk 使用仅限书面语言的交流方式面临着挑战。多年前,我了解到如果人们没有从我写的东西中理解我的意思,我需要写得更清楚,而不是因为误读而责备他们。如果你想让每个人都知道你的问题是特别的和不同的,那就说清楚。你也会得到更好的答案。一个简单的“我知道 xyz,我已阅读 [link to other question],我在问 abc”通常可以解决问题。

标签: c linux multithreading concurrency multicore


【解决方案1】:

我查看了 glibc,每次调用 vfprintf 都会在流上调用 POSIX flockfile (_IO_flockfile) 和 funlockfile (_IO_funlockfile)。

因此,调用中的字符不会与来自另一个线程的调用中的字符交错,因为只有一个线程可以锁定 stdoutstderr

不过,关于跨多个线程的多个调用的顺序,所有的赌注都没有了。

【讨论】:

  • 好的,这就是我期待的答案。而且我同意在各个线程之间进行排序。有人对这个答案有疑问吗?
  • 此外,C2011 具有线程支持,它说明了关于在单个调用中跨线程锁定单个 I/O 通道的相同内容。但是,标准没有说明如果一个线程写入 stdout 而另一个线程写入 stderr 会发生什么。由于并发执行,这些输出可能会在屏幕上交错。
【解决方案2】:

没有。即使在单线程程序中,由于不同的缓冲规则,您也可以获得交错。默认情况下,stdout 是行缓冲的,而 stderr 是非缓冲的。您可以通过以下方式使它们都不受缓冲:

   setvbuf(stdout, NULL, _IONBF, 0)

另见stdout thread-safe in C on Linux?,尤其是R.'s 答案。还有 Jonathan Leffler 的 comment

编辑: 默认情况下,标准输出将在每行末尾或缓冲区已满时为fflush'd。后者可能发生在一行的中间。然后,如果 stdout 和 stderr 都具有相同的底层文件描述符,则输出 fprintf(stderr,... 可以插入到一行的中间。

但情况可能更糟。通常您希望将 stderr 和 stdout 都重定向到文件或管道。我的系统说明中setbuf(3) 的手册页:

如果一个流引用一个终端(就像标准输出通常那样),它是行缓冲的。默认情况下,标准错误流 stderr 始终是无缓冲的。

所以在这种情况下,stdout 变成了 block 缓冲的,实际上似乎几乎 每个 到 stderr 的输出都与 stdout 的输出交错。这可以通过添加来缓解:

   setlinebuf(stdout);

或者通过使标准输出无缓冲。

【讨论】:

  • 你会在单线程代码中得到什么交错?一个printf 将在另一个printf 开始之前完成写入。我不明白你在说什么,抱歉。
  • 默认情况下,当缓冲区已满时,stdout 将在每一行的末尾fflushd。后者可能发生在一行的中间。然后,如果 stdout 和 stderr 都具有相同的底层文件描述符,则输出 fprintf(stderr,... 可以插入到行的中间。
  • 另见 Jonathan Leffler 对stackoverflow.com/a/12989477/318716 的评论。
猜你喜欢
  • 1970-01-01
  • 2015-12-07
  • 2014-04-27
  • 2010-09-05
  • 1970-01-01
  • 2013-04-19
  • 2018-06-04
  • 2011-06-18
相关资源
最近更新 更多