2016-09-10 5 views
1

は、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は、メインスレッドが戻る前に他のスレッドがジョブを開始することができないほど遅すぎると言う人もいます。しかし、printfwrite(2)に置き換えると、スレッドが時折順番に行を印刷する予想出力が になります。

どのようにこの現象を説明できますか?

バッファリングは、デフォルトでは端末出力がラインバッファされているので、それとはまったく関係ありません。 writeprintfの両方に該当する必要があります。

スレッド安全性を提供するために何らかの種類のブロッキング技術を使用していても、出力がスクランブリングを防ぐのはどういうことでしょうか?

+6

バッファリングに関する問題です。あなたは 'write(2)'と 'fwrite(3)'を混同しています。 'write(2)'は低水準関数でバッファリングされていません。 'fwrite(3)'は 'stdio'関数であり、デフォルトでバッファされます。 'stdout'はバックグラウンドスレッドでブロックバッファに入れられ、親にはラインバッファされたままなので、その効果があります。両方のスレッドに 'setbuf(stdout、NULL)'を追加して比較してください。 –

+0

もう一方のスレッドの出力はまだ端末に送られますので、いつものようにラインバッファしてはいけませんか? – ilkkachu

+4

"行バッファリング"は、 "端末"ではなく、 'stdio'の特徴です。 'write(2)'は 'stdio'を使わないのでバッファされません。 –

答えて

1

これは速度のために生まれつきです。 とループの間にusleepに電話をかけ、値を少し調整すると、いくつかの回線を混在させることができます。

stdioのロックにより、1つのスレッドがstdoutのロックを1回または2回取得できなかった場合、数ミリ秒間スリープする可能性があります(これにより、他のスレッドはループを完了できます)。ミキシングがたくさんあります。さらにミキシングしたい場合は、usleepもループに入れる必要があります。

私のマシンでは、親のループの前にusleep(50)があり、両方のループの中でusleep(1)が交互の行になります。

+0

'sched_yield'は私のマシンで'これはまさに私が探しているものです。ありがとうございました! –

関連する問題