[英]Partially thread-safe dictionary
我有一個類維護一個緩存一些數據的私有Dictionary
實例。
該類使用ReaderWriterLockSlim
從多個線程寫入字典。
我想在課外公開字典的值。
什么是線程安全的方法呢?
現在,我有以下內容:
public ReadOnlyCollection<MyClass> Values() {
using (sync.ReadLock())
return new ReadOnlyCollection<MyClass>(cache.Values.ToArray());
}
有沒有辦法這樣做而不需要多次復制集合?
我正在使用.Net 3.5(不是4.0)
我想在課外公開字典的值。 什么是線程安全的方法呢?
你有三個選擇。
1)復制數據,分發副本。 優點:無需擔心線程安全訪問數據。 缺點:客戶獲得過時數據的副本,而不是新鮮的最新數據。 而且,復制是昂貴的。
2)在讀取時,分發一個鎖定底層集合的對象。 您必須編寫自己的只讀集合,該集合引用了“父”集合的鎖定。 仔細設計兩個對象,以便無法實現死鎖。 優點:從客戶的角度來看“正常”; 他們獲得最新數據,而不必擔心鎖定。 缺點:為您做更多的工作。
3)將問題提交給客戶。 公開鎖定,並要求客戶端在使用之前鎖定數據本身的所有視圖。 優點:沒有為你工作。 缺點:為客戶提供更多的工作,他們可能不願意或無法做的工作。 死鎖等風險現在成為客戶的問題,而不是您的問題。
如果您想要獲取字典當前狀態的快照 ,那么您可以使用此集合類型進行其他任何操作。 這與ConcurrentDictionary<TKey, TValue>.Values
屬性使用的技術相同。
如果您在枚舉時修改了集合,如果不介意拋出InvalidOperationException
則可以返回cache.Values
因為它只是readonly(因此不能破壞字典數據)。
編輯 :我個人認為下面的代碼在技術上正確地回答了你的問題(因為,它提供了一種枚舉集合中的值而無需創建副本的方法)。 由於他們在編輯/評論中已經解釋過的原因,一些開發人員比我強烈建議反對這種方法更有信譽。 簡而言之: 這顯然是一個壞主意。 因此,我將離開答案,但建議你不要使用它。
除非我遺漏了某些內容,否則我相信您可以將您的值公開為IEnumerable<MyClass>
而無需使用yield
關鍵字復制值:
public IEnumerable<MyClass> Values {
get {
using (sync.ReadLock()) {
foreach (MyClass value in cache.Values)
yield return value;
}
}
}
但是請注意(我猜你已經知道這一點),這種方法提供了惰性求值 ,這意味着上面實現的Values
屬性不能被視為提供快照 。
換句話說......好吧,看看這段代碼(我當然會猜測你這類的一些細節):
var d = new ThreadSafeDictionary<string, string>();
// d is empty right now
IEnumerable<string> values = d.Values;
d.Add("someKey", "someValue");
// if values were a snapshot, this would output nothing...
// but in FACT, since it is lazily evaluated, it will now have
// what is CURRENTLY in d.Values ("someValue")
foreach (string s in values) {
Console.WriteLine(s);
}
因此,如果要求此Values
屬性等同於訪問該屬性時cache
中的內容的快照 ,那么您將不得不進行復制。
(開始280Z28):以下是一個不熟悉“C#做事方式”的人如何鎖定代碼的例子:
IEnumerator enumerator = obj.Values.GetEnumerator();
MyClass first = null;
if (enumerator.MoveNext())
first = enumerator.Current;
(結束280Z28)
回顧下一個可能性,只是公開ICollection接口,所以在Values()中你可以返回自己的實現。 此實現僅使用Dictioanry.Values上的引用,並始終使用ReadLock訪問項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.