2012-04-17 12 views
3

私はdoubleの共有変数を持っています。この変数は2つのスレッドによってアクセスされます。一方のスレッドは変数を書き込むだけですが、他方のスレッドは変数を読み込みます。共有変数の競合条件

ここでも競合状態はありますか?はいの場合、C++でアトミックアクセスを実装する "簡単な"方法がありますか?書き込みよりもはるかに多くの読み込みが行われる場合、効率的に実装するにはどうすればよいですか?変数にvolatileとマークする必要がありますか?

編集:OK「リーダー」スレッドはデータのバッチに対して定期的に機能し、新しい値の伝播は時間に影響されません。複雑なインターロックを実装するのではなく、テストする良い方法がないので、ライタースレッドが書き込む別の一時変数を宣言することができます。リーダが1バッチで終了すると、実際の変数に一時的に値を伝播させることができます。それは競争条件なしであろうか?

+0

@Jesse:多くのコンパイラは、まだそのヘッダの作業の実装を持っていませんが。 –

+0

シンプルなミューテックスは、あなたが良い値を読んでいることを確認するためにここで働くことができます。 mutexは、書込みスレッドが変数を使用しているときに変数へのアクセスをブロックし、完了したときに読み込みスレッドが自分の仕事を行うためにロックを解除します。 UNIXとWindowsの両方で、実装は非常に簡単です。 – Chris911

+0

@ Chris911:mutexは不必要に高価で、1つのスレッドをブロックする可能性があります。可能な限り待ち時間のない実装が可能です。 –

答えて

8

はい、ほとんどのプロセッサでdouble変数がアトミックではないため、競合状態が発生します。

3倍を使用します(パフォーマンスを低下させる誤った共有を避けるために、余分な埋め込みがある配列も可能です)。

1人は読者が所有し、1人は作家が所有し、もう1人は手渡されています。

書き込みを行う:書き込みスロットに書き込み、書き込みスロットのポインタ/インデックスをハンドオフスロットのインデックスでアトミックにスワップします(たとえば、InterlockedExchange)。インデックスはポインタサイズかそれより小さいので、変数が適切に整列されている限り、アトミックスワッピングは簡単です。偶然、あなたのプラットフォームがメモリバリアの有無にかかわらずインタロックされた交換を提供している場合は、それを使用してください。

読み込み:読み取りスロットのポインタ/インデックスを、ハンドオフ変数のインデックスでアトミックにスワップします。次に、読み取りスロットを読み取ります。

読み取りスレッドは、最新のスロットと前のスロットの間でバウンドする傾向があるため、実際にはバージョン番号も含める必要があります。読んでいるときは、スワップの前と後の両方を読んで、それ以降のバージョンのものを使います。

または、C++ 11では、std::atomicを使用してください。

警告:上記は、シングルライター/シングルリーダー(この質問の特定のケース)でのみ機能します。複数ある場合は、リーダライタのロックなどを考えて、変数へのアクセスをすべて保護してください。

+0

編集をご覧ください。 –

+0

パフォーマンスにどのような影響がありますか?私は毎秒数百回の読書を話していますが、書き込みは1時間に1回のように起こることがあります。 –

+0

@ Jakub:毎秒何百回も何も起こらず、パフォーマンスについても心配する必要はありません。それが1秒間に数十回行われた場合、それは心配する時間であり、私の提案は依然として最も速いものの1つになると思います。 –

0

あなたは読み込み/プリミティブ型の書き込みについて説明しこれを見てとることをお勧めします:

Are C++ Reads and Writes of an int Atomic?

+1

これはどうすれば 'double'の助けになりますか?通常は' int'と同じサイズではなく、異なる整列要件もありますか? –

+0

私は、そのスレッドから抜け出したいと思っていたキーテイクアウェイは、あなたが使用しているシステムの基盤となるアーキテクチャーに依存している(実際には、マルチバイトx64命令は、コンパイラ(つまり、http://msdn.microsoft.com/en-us/library/aa290049%28VS.71%29.aspx)など。あなたが指摘したように、それは原子ではないと仮定してそこから移動することは安全です。私はそれを少しだけ明確にしてくれました。 –

関連する問題