假设我有两个线程可以将某些内容(相对较长)打印到stderr
或stdout
,这两个流的功能是线程安全的,因为它们永远不会#34;交织"字符?所以,例如,如果我有"你好,世界",我永远不会得到" HHellllo,WorldWorld"或者其他任何交错?这适用于x86,GCC,Linux> 3.0。
答案 0 :(得分:4)
我看了一下glibc,每次拨打vfprintf
都会调用POSIX flockfile
(_IO_flockfile
)和funlockfile
(_IO_funlockfile
)流。
因此,调用中的字符不会与来自另一个线程的调用中的字符交错,因为只有一个线程可以锁定stdout
或stderr
。
关于跨越各个线程的多个调用的排序,所有的赌注都是关闭的。
答案 1 :(得分:1)
没有。即使在单线程程序中,由于不同的缓冲规则,您也可以进行交错。默认情况下,stdout是行缓冲的,而stderr是无缓冲的。您可以通过以下方式使它们无缓冲:
setvbuf(stdout, NULL, _IONBF, 0)
另见stdout thread-safe in C on Linux?,特别是R.'s回答。还有Jonathan Leffler的comment。
编辑:默认情况下,stdout在每行末尾或缓冲区已满时为fflush
。后者可能发生在一条线的中间。然后,如果stdout和stderr都具有相同的底层文件描述符,则输出fprintf(stderr,...可以插入到行的中间。
但情况会更糟。通常,您希望将stderr和stdout重定向到文件或管道。系统上setbuf(3)
的手册页注释:
如果流引用终端(正如stdout通常那样),则它是行缓冲的。默认情况下,标准错误流stderr始终是无缓冲的。
所以在这种情况下,stdout变为 block -buffered,实际上似乎几乎每个输出到stderr都与stdout的输出交错。这可以通过添加来缓解:
setlinebuf(stdout);
或者使stdout无缓冲。