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