簡體   English   中英

部分線程安全的字典

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM