これは素晴らしい質問です。
まず、C ++ 98 / C ++ 03には「スレッド」の概念がありません。したがって、その世界では、問題は無意味です。
C ++ 0xはどうですか?Martinhoの答えを見てください(私が驚いたことは認めます)。
C ++ 0x以前の特定の実装はどうですか?たとえば、basic_streambuf<...>:sputc
GCC 4.5.2( "streambuf"ヘッダー)のソースコードは次のとおりです。
int_type
sputc(char_type __c)
{
int_type __ret;
if (__builtin_expect(this->pptr() < this->epptr(), true)) {
*this->pptr() = __c;
this->pbump(1);
__ret = traits_type::to_int_type(__c);
}
else
__ret = this->overflow(traits_type::to_int_type(__c));
return __ret;
}
明らかに、これはロックを実行しません。そしてどちらもしませんxsputn
。そして、これは間違いなくcoutが使用するstreambufのタイプです。
私が知る限り、libstdc ++はストリーム操作のいずれについてもロックを実行しません。そして、それは遅いので、私は何も期待しませんでした。
したがって、この実装では、2つのスレッドの出力が(単にインターリーブするだけでなく)互いに破壊する可能性があることは明らかです。
このコードはデータ構造自体を破壊する可能性がありますか?答えは、これらの機能の可能な相互作用に依存します。たとえば、あるスレッドがバッファをフラッシュしようとしたときに、別のスレッドが呼び出しを試みた場合、どうなるかxsputn
などです。これは、コンパイラとCPUがメモリのロードとストアを並べ替える方法を決定する方法に依存する場合があります。確かに注意深い分析が必要です。2つのスレッドが同じ場所を同時に変更しようとした場合のCPUの動作にも依存します。
つまり、現在の環境で正常に機能しても、ランタイム、コンパイラー、またはCPUのいずれかを更新すると破損する可能性があります。
エグゼクティブサマリー:「そうしない」適切なロックを行うロギングクラスを構築するか、C ++ 0xに移動します。
弱い代替手段として、coutをunbufferedに設定できます。バッファに関連するすべてのロジックをスキップしてwrite
直接呼び出す可能性があります(保証はされません)。それは法外に遅いかもしれませんが。