2010-12-07 6 views
6

私はスレッドセーフ動作でなければならないいくつかのコードを持っているが、このようになります。ロックとインターロック操作を混在させても安全ですか?

 

protected long m_RunningValue 
protected long m_RunningCounter 
protected object m_Lock = new object(); 

public long RunningValue { get { return Interlocked.Read(m_RunningValue); } } 
public long RunningCounter { get { return Interlocked.Read(m_RunningCounter); } } 

public void DoCalculation(int newValue, int newQuantity) 
{ 
    lock(m_Lock) 
    { 
     Interlocked.Add(ref m_RunningValueA, newValue); 
     Interlocked.Add(ref m_RunningCounter, newQuantity); 
     if(Interlocked.Read(ref newQuantity) == 0) 
     { 
     ...m_RunningValue gets further modified here 
     } 
    } 
} 
 

値とカウンタまたはIF(...)ブロックに影響を与える可能性が競合状態の両方をロックする必要があります計算、しかし、彼らは読んでいるときには全く同期する必要はありません。つまり、カウンターと値の両方が読み取れる間にカウンタと値が変化すると、それは100%OKです。

読み取り時のインターロックは、64ビット値のスレッドセーフティ読み取りのためのものです。

  1. このようなインターロックとロックは混在していますか?私はそれらを混在させることは安全ではありませんが、混乱は微妙なバグを導入する素晴らしい方法であること、あるいはシステムレベルでこれが関連するデータ構造を破壊する可能性がある場合には解明できません。

  2. プロパティ(get()メソッドの周りにReaderWriterSlimのロックを保存する目的を完全に無効にするこのすべてのインターロック(64ビット.NET 4.0ランタイム)のコストはありますか?編集されたバージョンに関して

+0

'newQuantity'で連動して読み込む必要はありません。パフォーマンスに関しては、読み込みと更新の相対的な組み合わせに依存していると推測します。重要なのであれば、推測ではなくベンチマークする必要があります。 –

+0

連動した操作とロックの混在が問題を引き起こす理由はありません。 – casablanca

+0

なぜAnonの答えが正しいのか分かりません。インターロックなしでロック内で操作を行う場合は、プロパティの読み込みをインターロックする必要がありますか? – Chuu

答えて

5

、これは、スレッドセーフであることが保証さないです。

32ビットプラットフォームを考えてみましょう。つまり、2つの別々の操作で64ビットのlong値にアクセスする必要があります。

1つのスレッドが数値の前半を読み取ってからCPUからスワップされ、値の後半がその背後で変更されている可能性があります。このスレッドは完全に無効な値を持つようになりました。

Readメソッドおよびインクリメント、デクリメントの64ビットのオーバーロード、および追加の方法は唯一System.IntPtrが64であるシステム上で、真にアトミックです:Interlocked.Readため

ドキュメントが明示的に言及してビット長。他のシステムでは、これらのメソッドはお互いに原子的ですが、データにアクセスする他の手段に関してはアトミックではありません。したがって、32ビットシステム上でスレッドセーフであるためには、のいずれかのアクセスと64ビット値は、Interlockedクラスのメンバーを介して行わなければなりません。

(強調鉱山)

EDIT:今、それが戻って編集されていますことを、これは少し愚かに見えますが、私はあなたには、いくつかの場所での連動ではなく、している場合は、そのポイントを作るためにそれをここに残しておきます他の人たち、それは無意味です。

関連する問題