簡體   English   中英

如何使調用內部集合線程安全?

[英]How to make a call internal collections thread-safe?

我有這樣的班級組成。 類聲明一個對象字典,這些對象本身具有一個內部字典對象。

    public class ValueObject
    {
        public float value = 0;
    }

    public class ValueDictionaryObject
    {
        private Dictionary<int, ValueObject> innerDict;

        public float GetTotalValue()
        {
            lock (((ICollection)this.innerDict).SyncRoot)
            {
                float total = 0f;
                foreach (var p in innerDict)
                    total += p.Value.value;
                return total;
            }
        }
    }

    public class OuterDictionaryObject
    {
        private Dictionary<int, ValueDictionaryObject> outerDict;

        public float GetTotalValueForSomeKey(int key )
        {
            lock (((ICollection)this.outerDict).SyncRoot)
            {
                return outerDict[key].GetTotalValue();
            }
        }
    }


    var outer = new OuterDictionaryObject();

從多個線程進行調用時出現問題,似乎發生了死鎖

float result = outer.GetTotalValueForSomeKey(key);

如何使此調用線程安全?

從發布的代碼中尚不清楚為什么會陷入僵局。 是的,您具有嵌套鎖獲取功能,這是死鎖的先決條件。 但是,這里沒有任何東西可以向我們展示您如何在某些情況下相對於此處看到的情況反轉了鎖獲取順序。

仍然...

您應該盡量避免在按住鎖的同時調用任何東西。 有時這是不可避免的(例如,訪問要同步訪問的集合的成員,這意味着您必須調用該集合的成員)。 但是,只有在對您要解決的問題至關重要時,才應撥打電話。

在這里,似乎您可以像這樣輕松地編寫代碼:

public class OuterDictionaryObject
{
    private Dictionary<int, ValueDictionaryObject> outerDict;

    public float GetTotalValueForSomeKey(int key )
    {
        ValueDictionaryObject vdo;

        lock (((ICollection)this.outerDict).SyncRoot)
        {
            vdo = outerDict[key];
        }

        return vdo.GetTotalValue();
    }
}

使用ConcurrentDictionary會產生類似的效果,因為直到對字典對象的同步訪問完成之前,您不會調用GetTotalValue()方法。 因此恕我直言,這也是一個不錯的選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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