2011-12-06 16 views
5

スレッドを識別するカウンタを使用しているマルチスレッドコード(質問Windows API Thread Pool simple exampleを参照)があります。InterlockedIncrementとEnterCriticalSection/counter ++/LeaveCriticalSection

InterlockedIncrementを使用してスレッドのコールバック関数でこのカウンタをインクリメントすることをお勧めしました。しかし、これはいくつかの並行処理の問題が発生したので、変数を適切にロックしていないようです。私はInterlockedIncrementを手動でクリティカルセクションを使用して置き換えました:EnterCriticalSection/counter ++/LeaveCriticalSectionこれは今では完全に機能します。

なぜそうですか? 2つのオプションが厳密に同等であるとは思われませんか? 私はスレッド数を約2つ(約10)起動することについて話しています。

+0

どのようにして、変数を適切にロックしていないようですか?どのような並行性の問題が発生しましたか? – LukeH

+0

'InterlockedIncrement'と友達はロックする必要はありません。単一のアセンブリ命令を実行します。あなたは、あなたが見ていた問題についてもっと説明することができますか? – Nate

+0

LukeH:カウンタは常に厳密に連続した整数の連続を与えるとは限りませんでした。ときどき0から始まるカウンタが実行していた:0 1 2 2 4 5 ... – WhitAngl

答えて

26

コードにはInterlockedIncrementが正しく使用されていません。

InterlockedIncrement(&(thread.threadCount)); 
DWORD tid = (thread.threadCount-1)%thread.size(); 

これはthread.threadCountのアトミックインクリメントを実行しますが、代わりにアトミック・インクリメント値を保存するの、あなたはそれを無視して(その間に別のスレッドによってインクリメントされた可能性があります)thread.threadCount変数に戻ります。

場合によっては、2つのスレッドがほぼ同時にInterlockedIncrementを実行し、1から2、次に2から3をインクリメントします。両方のスレッドはthread.threadCountを読み込み、3を返します(1を減算して最終結果を得ます)。 2の)。

正しいコードは、一意のインクリメントされた値がInterlockedIncrementによって返される

LONG tidUnique = InterlockedIncrement(&(thread.threadCount)); 
DWORD tid = (tidUnique-1)%thread.size(); 

あります。一意の値を表示する場合は、計算でその値を使用する必要があります。

関連する問題