1. ホーム
  2. c++

[解決済み] coutは同期化/スレッドセーフですか?

2022-09-12 06:02:13

質問

一般に、ストリームは同期されないと仮定して、適切なロックを行うのはユーザ次第です。しかし、以下のようなことは可能でしょうか? cout のようなものは、標準ライブラリで特別な扱いを受けるのでしょうか?

つまり、もし複数のスレッドが cout を破損させることができるでしょうか? cout オブジェクトを破損することはないのでしょうか?同期してもランダムにインターリーブされた出力が得られることは理解できますが、そのインターリーブは保証されているのでしょうか。つまり cout を複数のスレッドから使用しても安全なのでしょうか?

これはベンダ依存ですか?gccはどうなっているのでしょうか?


重要 : もしあなたが「はい」と答えた場合、何らかの証拠が必要ですので、何らかの参考資料を提示してください。

私の懸念は、基礎となるシステムコールについてではなく、それらは問題ありませんが、ストリームはその上にバッファリングのレイヤーを追加します。

どのように解決するのですか?

C++03標準では、それについて何も言っていません。スレッドセーフであることが保証されていない場合は、スレッドセーフでないものとして扱う必要があります。

ここで特に興味深いのは cout がバッファリングされていることです。たとえ write (またはその特定の実装でその効果を達成するものが何であれ) の呼び出しが相互に排他的であることが保証されている場合でも、バッファは異なるスレッドによって共有されるかもしれません。これは、ストリームの内部状態の破損にすぐにつながります。

また、バッファへのアクセスがスレッドセーフであることが保証されている場合でも、このコードでは何が起こると思いますか?

// in one thread
cout << "The operation took " << result << " seconds.";

// in another thread
cout << "Hello world! Hello " << name << "!";

おそらく、ここにある各行が相互に排他的に動作するようにしたいのでしょう。しかし、実装はどのようにそれを保証できるでしょうか?

C++11では、いくつかの保証があります。FDISでは§27.4.1 [iostream.objects.overview]で次のように書かれています。

同期 (§27.5.3.4) 標準 iostream オブジェクトのフォーマットされた入力 (§27.7.2.1) とフォーマットされていない出力 (§27.7.3.1) の関数や標準 Cストリームへの複数のスレッドによる同時アクセスは、データ競合 (§1.4.2) を生じてはならない。 は、データ競合(§1.10)を生じてはならない。[注意:複数のスレッドによるこれらのオブジェクトやストリームの同時使用を避けたい場合、ユーザは同期をとる必要があります。 注意:インターリーブ文字を避けるためには,利用者は,複数のスレッドによるこれらのオブジェクト及びストリームの同時使用を同期させなければならない。- エンドノート ]。

そのため、破損したストリームを得ることはありませんが、出力がゴミにならないようにするには、手動で同期させる必要があります。