ビットフィールドがコンパイラに依存することは知っていますが、最新の g++ および Visual C++ 2010 を使用したビットフィールドのスレッド セーフに関するドキュメントは見つかりませんでした。
ビットフィールドメンバーの操作はアトミックですか?
ビットフィールドがコンパイラに依存することは知っていますが、最新の g++ および Visual C++ 2010 を使用したビットフィールドのスレッド セーフに関するドキュメントは見つかりませんでした。
ビットフィールドメンバーの操作はアトミックですか?
残念ながら、「スレッドセーフ」は、プログラミングでは非常に過負荷な用語です。
ビットフィールドへのアトミックアクセスを意味する場合、答えはノーです(少なくとも私が知っているすべてのプロセッサで)。32 ビット マシンでは 32 ビットのメモリ ロケーションにアトミックアクセスできますが、それは 32 ビット値全体を読み書きすることを意味するだけです。これは、別のスレッドが同じことをしないという意味ではありません。停止しようとしている場合は、同期が必要になる可能性があります。
ビットフィールドへの同期アクセスを意味する場合、アクセスをより高いレベルの同期プリミティブ (アトミック操作で構築されることが多い) でラップしない限り、答えもノーです。
要するに、コンパイラは、追加の作業なしではビット フィールドへのアトミックアクセスまたは同期アクセスを提供しません。
それは役に立ちますか?
編集: Dan Grossman 博士は、UOregon の CS 部門のページで見つけた原子性と同期に関する 2 つのすばらしい講義を行っています。
ビットフィールドに書き込むとき、別のスレッドが同じ構造内の任意の (同じまたは異なる) ビットフィールドにアクセス (読み取りまたは書き込み) しようとすると、未定義の動作が発生する時間ウィンドウが存在する場合があります。起こる。ビット フィールドを読み取る場合、別のスレッドが同じ構造体のビット フィールドに書き込もうとすると、未定義の動作が発生するタイム ウィンドウが存在する場合があります。
問題のビットフィールドに個別の変数を実際に使用できない場合は、複数のビットフィールドを整数に格納し、ビットフィールド構造と 32 ビット整数の間の和集合を作成することで、それらをアトミックに更新できる場合があります。次に、CompareExchange シーケンスを使用します。
このアプローチがうまく機能するには、ステップ 2 ~ 4 が高速である必要があります。時間がかかるほど、手順 5 の CompareExchange が失敗する可能性が高くなるため、CompareExchange が成功するまでに手順 2 ~ 4 を再実行する必要がある回数が増えます。
スレッドセーフな方法でビットフィールドを更新する場合は、ビットフィールドを個別のフラグに分割し、通常int
のsを使用してそれらを格納する必要があります。個別のマシンワードへのアクセスはスレッドセーフです(ただし、マルチプロセッサシステムでの最適化とキャッシュコヒーレンシを考慮する必要があります)。
Windows連動機能を見る
シンプルにatomic.AddInt32の例を使用してください:
atomic.AddInt32(&intval, 1 << 0) //set the first bit
atomic.AddInt32(&intval, 1 << 1) //set the second bit
atomic.AddInt32(&intval, -(1 << 1 + 1 << 0)) //clear the first and second bit
コードは Go にあります。C++ には、atomic.AddInt32 のようなものもあると思います。