2012-10-20 68 views
2

假設我有兩個線程可以輸出stderrstdout這樣的東西(相對較長),這兩個線程對於線程安全的函數是不會「交錯」字符的?舉例來說,如果我有「你好,世界」,我永遠不會得到「HHellllo,WorldWorld」或其他什麼交錯?這適用於x86,GCC,Linux> 3.0。對``fprintf(stdout,...)`和`fprintf(stderr,...)```都保證與多線程非交錯?

+0

可能的重複[線程安全可以在同時運行的線程中調用printf?](http://stackoverflow.com/questions/4353651/is-it-thread-safe-to-call-printf-in-線程即同時運行) –

+0

@JensGustedt:我看到了,但它不回答* * stderr和stdout是否都是線程安全的。在某處我讀到'stderr'不是這種情況,我需要確認。 –

+0

可能重複[stdout線程安全在Linux上的C?](http://stackoverflow.com/questions/467938/stdout-thread-safe-in-c-on-linux) –

回答

4

我看了看glibc的,並且每次調用vfprintf將調用POSIX flockfile_IO_flockfile)和funlockfile_IO_funlockfile)在流。

因此,呼叫中的字符不會與來自另一線程的呼叫中的字符交錯,因爲只有一個線程可以鎖定stdoutstderr上的鎖定。

儘管在各個線程中多次調用的順序,但所有賭注都是關閉的。

+0

好吧,這是我期待的答案。我同意訂購關閉各個線程。任何人有這個問題? –

+1

此外,C2011有線程支持,它說等價的東西關於鎖定但是,標準並沒有說明如果一個線程在stdout上寫入而另一個線程在stderr上寫入時會發生什麼;這些輸出可能因爲併發執行而在屏幕上交錯。 –

1

不會。即使在單線程程序中,由於不同的緩衝規則,您可以獲得交錯。默認情況下,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)手冊頁在我的系統說明:。

如果流是指終端(通常stdout都是這樣)它是行緩衝的標準誤差流stderr的是默認情況下始終未緩衝

所以在這種情況下,標準輸出變爲緩衝,實際上似乎幾乎輸出到標準錯誤與標準輸出交錯。這可以通過加入緩解:

setlinebuf(stdout); 

或者通過使stdout無緩衝。

+1

你會在單線程代碼中獲得什麼交錯?一個'printf'將在其他'printf'開始之前完成寫入。我不明白你在說什麼,對不起。 –

+2

默認情況下,當緩衝區已滿時,stdout將在每行結束時執行***或***。後者可能發生在一條線的中間。然後,如果stdout和stderr都具有相同的基礎文件描述符,則可以將輸出fprintf(stderr,...)插入到行的中間。 –

+0

另請參見Jonathan Leffler對http://stackoverflow.com/的評論a/12989477/318716。 –