2011-07-18 53 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; 
    } 
} 

問題a:線程安全嗎?如果是,爲什麼?這個非鎖定TryGetValue()字典訪問線程安全嗎?

問題b:這個double-TryGetValue()模式是如何調用的?

+0

旁註;對於'Hashtable',雙重檢查鎖定*的模式顯然是安全的。字典的安全性不太清楚。 –

回答

15

a)這不是線程安全的,因爲底層Dictionary本身不是線程安全的。如果另一個線程同時調用Add,則會發生未定義的行爲。

b)這實際上是在double-checked locking的嘗試。

我建議使用ConcurrentDictionary類,因爲它是爲這種情況設計的。如果您不打算使用.NET 4.0,另一個選擇是使用ReaderWriterLockSlim(或ReaderWriterLock)。

+0

-1 ReaderWriterLockSlim和ReaderWriterLock比'lock'貴得多,特別是在寫入時。使用這些函數的唯一原因是,當你爲每次寫入操作執行100或1000次讀取操作時,讀取鎖定的持續時間足以導致其他線程出現嚴重延遲。使用這個簡單的代碼(一個TryGetValue),'lock'語句就是正確的同步。 –

+2

@ csharptest.net這很苛刻;他的建議是'ConcurrentDictionary',這很好 - 而且由於裏德不是OP,**我們不知道**讀者/寫者的比率。對於我們所知道的,「ReaderWriterLockSlim」實際上可能沒有問題。 –

+1

@csharptest以下博客條目聲稱''ReaderWriterLockSlim'比'Monitor'的性能開銷大約是一個因子2.從您的評論中我預計超過10的因子。http://blogs.msdn.com/b/pedram/archive /2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx – CodesInChaos

2

不幸的是,沒有。

我帶着一個具有這個屬性的自定義HashMap。

缺陷位於rehash()函數中。

9

問題a:線程安全嗎?如果是,爲什麼?

它不僅不是線程安全的;如果在另一個線程正在重新組織散列桶時訪問,它也會拋出NullReferenceException異常。鎖定語句很快,不要回避它。

問題b:這個double-TryGetValue()模式是如何調用的?

它之所以被稱爲 '臭蟲' 被大多數人;)

+1

*這被大多數人稱爲'bug'*讓我失望LOL +1)+1 –