假設在C#中有多個線程正在訪問和更改的Dictionary<K, V>
對象。您希望某些操作是線程安全的。C#中的數據結構的慣用,保證互斥?
所以你達到了一個互斥體。在C#中,使用一個互斥體的標準方法是:
lock (someSharedObject)
{
// Mutual exclusion zone here.
myDictionary.Add(1, "hello");
}
的問題是,你在文檔僅僅依靠以保持未來的程序員直接訪問字典,繞過互斥:
myDictionary.Add(1, "hello");
我想讓編譯器阻止未來的程序員使用不受保護的字典。
我看到兩個普通可能性:
- 創建一個酷似詞典(比如,
LockedDictionary
),這保證了它的成員方法鎖定,但其他各方面的行爲像一個字典。 - 創建守衛訪問
Dictionary
一類,因此無需通過保護會調用者不能達到Dictionary
。
這些履行現在沒有人可以不受保護,至少意外地使用字典的願望屬性。我想討論兩者的利弊,然後要求你同意或不同意我的看法,並提出我可能忽略的解決方案。
的LockedDictionary
的好處是,它直觀的爲別人着想。它還允許對哪些方法需要鎖定以及程度進行細粒度控制。缺點是它不完全是Dictionary
,所以你不能將這個對象傳遞給一個預期會收到Dictionary
的函數。 (雖然你可以通過實現IDictionary
接近。)
移動到#2。保護類的好處是,你可以實現IDisposable
和使用它像這樣:
class DictionaryFortress {
Dictionary<K, V> realDict;
Object lockobject;
void Lock() {
Monitor.Enter(lockobject);
return DictionaryGuard(lockobject, realDict);
}
}
class DictionaryGuard : IDisposable {
public Dictionary<K, V> Dict {
get { return realDict; }
}
public void Dispose() {
Monitor.Exit(lockobject);
}
}
// in some class
DictionaryFortress dict = new DictionaryFortress(); // early on
// in a function, when we need to access dictionary contents...
using (DictionaryGuard guard = dict.Lock()) {
Dictionary<K, V> actualDict = guard.Dict;
// now you can pass actualDict anywhere; no one has to know that it's locked
}
的好處,當然是我們必須訪問原始的字典,所以我們沒有在如何約束我們可以使用它,我們可以通過它。缺點是使用它的開銷更大。用戶還可以在可用時保存對guard.Dict
的引用,然後在丟棄DictionaryGuard後使用它。
我傾向#2。我有沒有錯過任何優點和缺點?有沒有更好的方法來保護對我的字典的訪問,同時最大限度地減少濫用的風險?同樣,我的要求是一個健忘或粗心的程序員不能跳過鎖定階段。我的願望是它的習慣,方便和靈活。
你考慮['ConcurrentDictionary中'](http://msdn.microsoft。COM/EN-US /庫/ dd287191.aspx)? –
jrummell
2013-04-04 20:10:21
或其他線程安全集合的ConcurrentBag,ConcurrentQueue和ConcurrentStack。沒有重新發明輪子... – Pete 2013-04-04 20:11:17
謝謝。雖然我知道我確實在重新發明輪子,但我忘記了這些的存在。你會發布這個建議的答案嗎? – Philip 2013-04-04 20:18:49