は、Solaris 11.3の下で実行されている次のコードを考えてみましょう:はprintfのマルチスレッドの書き込み(2)バッファリング対
実行している時void *run(void *args) {
int i;
for (i = 0; i < 100; i++) {
printf("Line #%d printed by child\n", i + 1);
}
}
int main() {
pthread_t tid;
int ret = pthread_create(&tid, NULL, run, NULL);
int i;
for (i = 0; i < 100; i++) {
printf("Line #%d printed by parent\n", i + 1);
}
pthread_exit(NULL);
}
は、親スレッドは、常に新しく作成されたスレッドの前にその行のすべてを出力します。 pthread_create
は、メインスレッドが戻る前に他のスレッドがジョブを開始することができないほど遅すぎると言う人もいます。しかし、printf
をwrite(2)
に置き換えると、スレッドが時折順番に行を印刷する予想出力が になります。
どのようにこの現象を説明できますか?
バッファリングは、デフォルトでは端末出力がラインバッファされているので、それとはまったく関係ありません。 write
とprintf
の両方に該当する必要があります。
スレッド安全性を提供するために何らかの種類のブロッキング技術を使用していても、出力がスクランブリングを防ぐのはどういうことでしょうか?
バッファリングに関する問題です。あなたは 'write(2)'と 'fwrite(3)'を混同しています。 'write(2)'は低水準関数でバッファリングされていません。 'fwrite(3)'は 'stdio'関数であり、デフォルトでバッファされます。 'stdout'はバックグラウンドスレッドでブロックバッファに入れられ、親にはラインバッファされたままなので、その効果があります。両方のスレッドに 'setbuf(stdout、NULL)'を追加して比較してください。 –
もう一方のスレッドの出力はまだ端末に送られますので、いつものようにラインバッファしてはいけませんか? – ilkkachu
"行バッファリング"は、 "端末"ではなく、 'stdio'の特徴です。 'write(2)'は 'stdio'を使わないのでバッファされません。 –