OpenSceneGraph ライブラリで 3D レンダリングを行うマルチスレッド C++ アプリがあります。OSG のレンダー ループを、boost::threads を使用して別のスレッドとして開始し、共有状態を含むデータ構造をスレッドに渡すことを計画しています。レンダー ループをかなりタイトにする必要があり、OSG 自体がロックする必要がないようにしようとするため、同期には重すぎるもの (ミューテックスなど) を避けようとしています。共有状態のほとんどは、スレッドが開始される前に設定され、変更されることはありません。変更が必要なデータがいくつかありますが、これをダブル バッファリングする予定です。ただし、レンダリングを一時停止し、後でレンダリングを再開するようにスレッドに通知するための単純なブール値と、それを強制終了するための別のブール値があります。どちらの場合も、アプリ スレッドが bool を設定し、レンダリング スレッドはそれを読み取るだけです。これらのブールへのアクセスを同期する必要がありますか? 私が知る限り、発生する可能性のある最悪の事態は、一時停止または終了する前に、レンダリング ループが余分なフレームの間継続することです。
5 に答える
標準で定義された同時実行性を持つ C++11 以降ではstd::atomic<bool>
、この目的で使用します。http://en.cppreference.com/w/cpp/atomic/atomicから:
あるスレッドがアトミック オブジェクトに書き込み、別のスレッドがそれから読み取る場合、動作は明確に定義されています (データ競合の詳細については、メモリ モデルを参照してください)。
次の古い答えは、一部のコンパイラと一部のオペレーティング環境で過去のある時点で真実だった可能性がありますが、今日は信頼すべきではありません。
その通りです。この場合、ブール値を同期する必要はありません。volatile
ただし、以前の読み取りをスレッドにキャッシュするのではなく、コンパイラが毎回メモリから実際に読み取るように、それらを宣言する必要があります (これは簡単な説明ですが、この目的のために行う必要があります)。
次の質問には、これに関する詳細情報があります: C++ スレッド、共有データ
単純にインターロック変数を使用しないのはなぜですか?
ここでは本格的なミューテックスは必要ないと思いますが、待機プリミティブをサポートする同期オブジェクトを使用していない場合、レンダー スレッドは「サスペンド」状態でビジー待機する必要があります。
ただし、さまざまなインターロック交換プリミティブの使用を検討する必要があります (Windows では InterlockedExchange)。bool からの読み取り/書き込みがアトミックではないためではなく、コンパイラが単一のスレッドでメモリ アクセスを並べ替える奇妙な動作がないことを確認するためです。
このスレッドには、特に単純なデータ型のスレッド セーフに関する情報と議論がもう少しあります。