2011-08-03 21 views
1

グローバルlong countがあります。
スレッドAはトリッキーなInterlockedDecrementとCriticalSection

EnterCriticalSection(&crit); 
// .... do something 
count++;      // (*1) 
// .. do something else 
LeaveCriticalSection(&crit); 

スレッドBは、(* 1)、私はクリティカルセクションの下で午前

InterlockedDecrement(&count); // (*2) not under critical secion. 

を行いません。 (* 2)では、私はそうではありません。

InterlockedIncrement()なしで(* 1)安全ですか? (保護されたクリティカルセクションです)。
(* 1)にInterlockedIncrement()が必要ですか?
私は賛否両論を論じることができると感じます。

+0

私は 'something do'コードのためにそこにロックを張っていますか? –

答えて

4

いずれかを使用し、混用しないでください。

InterlockedDecrementはアトミックであることが保証されていますが、operator++はそうではありませんが、この場合はアーキテクチャによって異なる場合があります。この場合、実際には変数countを実際には保護していません。

あなたは、単純なinrecrement /デクリメント操作をしたいように見えることを考えると、私はあなたが単にこの場合、クリティカルセクションを削除し、関連するInterlocked*機能を使用することを示唆しています。

3

どちらのスレッドが同じクリティカルセクションInterlockedDecrement/InterlockedIncrementまたはのいずれかを使用する必要があります。ミキシングとマッチングが正しく機能する理由はありません。

は、次の一連のイベントを考えてみましょう:

Thread A: enter the critical section 
Thread A: read count into a register 
Thread A: increment the value in the register 
Thread B: InterlockedDecrement(&count) <<< There's nothing to stop this from happening! 
Thread A: write the new count 
Thread A: leave the critical section 

最終結果:あなたはデクリメントを失ってしまいました!

クリティカルセクションに役立つ(意図的に単純化した場合)メンタルモデルはこれです。クリティカルセクションに入ると、他のスレッドが同じクリティカルセクションに入るのを防ぐことができます。他のスレッドが同期が必要な他の処理を自動的には行わないようにします。

そしてすべてInterlockedDecrementは、減分のアトミック性を保証します。変数の古いコピーの計算を実行しているスレッドが他のスレッドを実行してから、その結果を書き戻すことはできません。

1

はい、そうです。

それ以外の場合は、その可能性が:

値が読み出され
  1. 値がアトミック

  2. にインクリメントされる元の値は、前のアトミック更新を無効、インクリメントと書かれている

さらに別のものをロックするのに役立たないので、同じクリティカルセクションが必要です。 :)