2009-04-08 10 views
1

私はマルチスレッドのアプリケーションで汎用辞書を持っています。ロックを実装する私はプロパティを作成しました。今は書く場合スレッディング:汎用辞書のロック

static object myLock=new object(); 
Dictionary<key,SomeRef> dict=new Dictionary<key,SomeRef>(); 

public Dictionary<key,SomeRef> MyDict{ 
     get{ 
     lock(myLock){ 
     return dict; 
     } 
    } 
} 

コード#1

MyDict.TryGetValue 

又はコード#2

var result=MyDict.Values; 
foreach(var item in result){ 
//read value into some other variable 
} 

ので、一方IM runnigコード1又は2と同時に、いくつかの他のスレッドしようとした場合..clear dictのような辞書の書き込み操作を行うか、新しい項目を追加する。このソリューションは、スレッドセーフである(プロパティを使用します)。もしそうでなければ これを行う他の方法はありますか?

私は書き込み操作を言うとき、それはキーを作成して値を割り当てないと、プロパティチェックキーエキステイストを介してdictの参照を取ることができます。 (したがって私は不動産のセッターを使用しません)

答えて

4

いいえ、これはスレッドセーフではありません。

ロックは、辞書の内部(dict)インスタンスへの参照を取得することのみをロックします。ユーザーが辞書に追加しようとしたとき、または辞書から読み込もうとしたときにロックされません。

スレッドセーフなアクセスを提供する必要がある場合は、辞書を非公開にしておき、辞書の値を取得/設定/追加する独自のメソッドを作成することをお勧めします。このようにして、必要な細かさで保護するためにロックを設置することができます。


これは次のようになります。

public bool TryGetValue(key thekey, out SomeRef result) 
{ 
    lock(myLock) { return this.dict.TryGetValue(thekey, out result); } 
} 
public void Add(key thekey, SomeRef value) 
{ 
    lock(myLock) { this.dict.Add(thekey, value) } 
} 
// etc for each method you need to implement... 

ここでの考え方は、クライアントが直接あなたのクラスを使用することで、あなたのクラスは、同期を処理します。値を繰り返し処理すると予想される場合(foreachステートメントなど)、リストに値をコピーして返すか、列挙子を直接提供するか(IEnumerator<SomeRef> GetValues())などを決定できます。

3

いいえ、これはlockedのコードだけが検索コードであるため、安全ではありません。何をする必要が

lock(MyDict) 
{ 
    if(MyDict.TryGetValue()... 
} 

lock(MyDict) 
{ 
    foreach(var item in MyDict.Values) ... 
} 

基本的な考え方は、ロック()ブロック内で作業コードを囲むことです。

+0

こんにちはアダムありがとう。 の違いは何ですか?(MyDict){if(MyDict.TryGetValue()...} と ロック(MyLock){if(MyDict.TryGetValue()...} –

+0

唯一の違いはロックオブジェクトです辞書(または他のリソース固有のオブジェクト)をロックするのは慣例にすぎません。同じ同期オブジェクトを使用している限り、あなたは大丈夫です。 –

2

実装はスレッドセーフであるとは限りません。スレッドセーフであるためには、読み取り/書き込みはすべてロックによって保護されている必要があります。内部ディクショナリへの参照を渡すことで、リソースにアクセスする人を制御することが非常に難しくなります。したがって、呼び出し元が同じロックを使用する保証はありません。

アクセスを同期しようとしているリソースがすべて自分のタイプに完全にカプセル化されていることを確認するのがよい方法です。そうすれば、そのタイプのスレッドの安全性を理解して推論するのがずっと簡単になります。