2017-03-21 7 views
0

私は、ライターと複数のリーダーが1つの並列コードを作成しています。ライターは最初から最後まで配列を塗りつぶし、リーダーは配列の要素に順番にアクセスします。擬似コードは、以下のようなものです:マルチスレッドシングルライターマルチリーダコードでintを使用するのは安全です

std::vector<Stuff> vec(knownSize); 
int producerIndex = 0; 
std::atomic<int> consumerIndex = 0; 

プロデューサースレッド:

for(a while){ 
    vec[producerIndex] = someStuff(); 
    ++producerIndex; 
} 

消費者スレッド:私はproducerIndex周り同期の任意の並べ替えを必要とする

while(!finished){ 
    int myIndex = consumerIndex++; 
    while(myIndex >= producerIndex){ spin(); } 
    use(vec[myIndex]); 
} 

ていますか?それは私が余分な時間を回すかもしれないように私はそれが更新されている間に古い値を読むということが起こる可能性が最悪のもののように思えます。私は何か不足していますか? myIndexへの各割り当てが一意であることを確認できますか?

+3

これは間違いなく 'producerIndex'のデータ競争です。これはあるスレッドから読み込まれ、別のスレッドに書き込まれます。 –

+0

はい、それは消費者が古い値か古い値+ 1の両方を読むことができる "良性のレース"のようですが、どちらもOKです。 produceIndexに実際には格納されていない値を読み取ることは可能ですか? –

+2

@BenJonesレースは未定義の動作です。古い値かもしれないし、新しい値かもしれない。しかし、それはwo(新しい上位バイトと古い下位バイト)を混在させることもできます。それともクラッシュしたり、他の奇妙なものを作り出したりする可能性があります。 – Christophe

答えて

3

コメントが指摘しているように、このコードにはデータ競争があります。コードにあなたが望むことができるかどうか推測するのではなく、ちょうどそれを修正してください。タイプをからstd::atomic<int>に変更し、ターゲットプラットフォーム。

0

配列はすべてキャッシュに保存されるため、すべてのスレッドには独自のコピーが割り当てられます。プロデューサが配列に新しい値を入れると、ストアアドレスに汚れたビットがセットされるので、値を使用する他のすべてのスレッドはRAMからキャッシュ内のそれ自身のコピーにキャッシュを取り出します。 つまり、多くのキャッシュミスが発生しますが、競合状態は発生しません。 :)

+0

これは現代のCPUの仕事(キャッシュが協調している; RAMが遅すぎる)とは異なりますが、C++の観点からは違いを知ることはできません。 – MSalters

関連する問題