2011-07-18 24 views
9
private object lockObj = new object(); 

private Dictionary<int, string> dict = new Dictionary<int, string>(); 

public string GetOrAddFromDict(int key) 
{ 
    string value; 

    // non-locked access: 
    if (dict.TryGetValue(key, out value)) 
     return value; 

    lock (this.lockObj) 
    { 
     if (dict.TryGetValue(key, out value)) 
      return value; 

     string newValue = "value of " + key; // place long operation here 
     dict.Add(key, newValue); 

     return newValue; 
    } 
} 

質問:スレッドセーフですか?はいの場合、なぜですか?このロックされていないTryGetValue()辞書アクセスはスレッドセーフですか?

質問b:このdouble-TryGetValue()パターンはどのように呼び出されますか?

+0

サイドノート。ダブルチェックされたロック*のパターンは、 'Hashtable'に対して明示的に安全です。それが辞書にとって安全かどうかは不明です。 –

答えて

15

a)基礎となるDictionary自体はスレッドセーフではないため、これはスレッドセーフではありません。別のスレッドが同時にAddを呼び出している場合は、未定義の動作が発生する可能性があります。

b)これは実質的にdouble-checked lockingの試みです。

代わりにConcurrentDictionaryクラスを使用することをお勧めします。このシナリオ用に設計されているためです。別のオプションは、.NET 4.0をターゲットにしていない場合はReaderWriterLockSlim(またはReaderWriterLock)を使用することです。

+0

-1 ReaderWriterLockSlimとReaderWriterLockは、特に書き込み時に 'ロック'よりはるかに高価です。これらを使用する唯一の理由は、書き込みごとに100または1000の読み込みを行い、読み取りロックの持続時間が他のスレッドにかなりの遅延を引き起こすほど重要である場合です。この単純な(1つのTryGetValue)コードでは、 'lock'ステートメントは正しい同期です。 –

+2

@ csharptest.netそれは厳しいです。彼の推薦は 'ConcurrentDictionary'だった。これはうまくいくだろうし、ReedはOPではないから、**リーダライターのレートは知りません**。 'ReaderWriterLockSlim'は実際にはうまくいくかもしれません。 –

+1

@csharptest次のブログエントリは、 'Monitor'に対する' ReaderWriterLockSlim'のパフォーマンスオーバーヘッドが約2倍であると主張しています。あなたのコメントから、10を超える要素が予想されました。http://blogs.msdn.com/b/pedram/archive /2007/10/07/performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx – CodesInChaos

2

悲しいことに、

このプロパティを持つカスタムHashMapを持ち歩いています。

この欠陥はrehash()関数にあります。

9

質問:スレッドセーフですか?はいの場合、なぜですか?

スレッドセーフではないだけでなく、他のスレッドがハッシュバケットを再編成している間にアクセスされると、NullReferenceExceptionをスローします。ロックステートメントは、邪悪な速さですが、避けてはいけません。

質問b:このdouble-TryGetValue()パターンはどのように呼び出されますか?

それはほとんどの人々によって 'バグ' と呼ばれています;)

+1

*ほとんどの人が「バグ」と呼んでいます* LOLにしました;)+1 –

関連する問題