如何使调用内部集合线程安全

本文关键字:线程 安全 集合 内部 何使 调用 | 更新日期: 2023-09-27 18:30:34

我有这样的类组成。类声明一个对象的字典,这些对象本身具有内部字典对象。

    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() 方法。所以恕我直言,这也是一个不错的选择。