2012-03-30 8 views
16

は最近、私はウェブサイトでこのコードを見てきましたし、私の質問は以下の通りです:マルチスレッド環境ではマルチスレッド時に単一のbool変数をロックする?

 private bool mbTestFinished = false; 

     private bool IsFinished() 
     { 
      lock(mLock) 
      { 
       return mbTestFinished; 
      } 
     } 

     internal void SetFinished() 
     { 
      lock(mLock) 
      { 
       mbTestFinished = true; 
      } 
     } 

mbTestFinishedへのアクセスをロックすることが本当に必要なのか?二つの理由から、私の意見では

+6

これはCPUキャッシュの読み込み(スレッド間ではうまくいかない)を保証する最も証明可能なメカニズムです - 'volatile'も機能しますが、複雑すぎる理由から*揮発性のインテント*ではなく、副作用) –

+4

@MarcGravell私はいつも「揮発性」の意志と考えていました。あなたが何かを説明する良いリンクをドロップする可能性がありますか? –

+1

@romkyns:この[回答](http://stackoverflow.com/a/4103879/158779)では、いくつかの洞察が得られます。 –

答えて

9

はい、必要です。 .Net環境ではいくつかの最適化が行われます。また、メモリ位置が頻繁にアクセスされると、データがCPUレジスタに移動されることがあります。したがって、この場合、mbTestFinishedがCPUレジスタ内にある場合、それを読み取るスレッドは誤った値を取得する可能性があります。したがって、揮発性キーを使用すると、この変数へのすべてのアクセスはレジスタではなくメモリの場所で行われます。 一方、私はこの発生の頻度を知らない。これは非常に低い頻度で発生する可能性があります。 MLOCKがをmbTestFinished変数に対してのみある場合

9

が、いや、ロックは、ここに不必要である:

  1. ブール変数は、割り当ては、たとえばlongのように引き裂く原因となることができない、したがって、ロックは必要ありません。
  2. 視認性の問題を解決するにはvolatileで十分です。 lockには暗黙のフェンスが導入されていますが、lockはアトミックでは必要ないため、volatileで十分です。
+0

これは、表示されているコードがロックを使用している*唯一のものであると仮定すると真です。 'mLock'が取られる場所が他にある場合、' volatile'への変換は物事を壊す可能性があります。 –

+0

@romkyns:はい、私はそれが自己完結型シナリオであると仮定しています。 – Tudor

4

は、それはやり過ぎのビットです。代わりに、volatileまたはinterlockedを使用することができます。どちらもユーザーモード構成のはスレッド同期のためです。 は(モニタ又はロックハイブリッドは、十分/ カーネルモードへ可能な限りから遷移を回避するように最適化されるという意味で、を構築しています。 「CLR via C#」という本には、これらの概念の詳細な説明があります。

関連する問題