C# 如何使呼叫内部集合线程安全?

C# 如何使呼叫内部集合线程安全?,c#,multithreading,dictionary,collections,thread-safety,C#,Multithreading,Dictionary,Collections,Thread Safety,我有这样的班级作文。类声明对象的字典,这些对象本身具有内部字典对象 public class ValueObject { public float value = 0; } public class ValueDictionaryObject { private Dictionary<int, ValueObject> innerDict; public float GetTotalValue

我有这样的班级作文。类声明对象的字典,这些对象本身具有内部字典对象

    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();

如何使此调用线程安全?

从您发布的代码中不清楚为什么会出现死锁。是的,您有嵌套锁获取,这是死锁的先决条件。但是这里没有任何东西可以告诉我们,在一些场景中,相对于我们在这里看到的场景,您是如何反转锁获取顺序的

还是

当你拿着锁的时候,你应该尽量避免呼叫任何东西。有时这是不可避免的(例如,访问正在同步访问的集合的成员,这意味着您必须调用该集合的成员)。但是你应该只在对你正在解决的问题至关重要的时候打电话

在这里,您似乎可以像这样轻松地编写代码:

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();
    }
}
公共类OuterDictionaryObject
{
专用词典;
公共浮点GetTotalValueForSomeKey(int key)
{
值字典对象vdo;
锁定(((ICollection)this.outerDict.SyncRoot)
{
vdo=外部输入[键];
}
返回vdo.GetTotalValue();
}
}

使用
ConcurrentDictionary
也会产生类似的效果,在同步访问dictionary对象完成之前,您不会调用
GetTotalValue()
方法。因此,我认为这也是一个不错的选择。

您有时会锁定内部词典,有时会锁定外部词典
GetTotalValue
GetTotalValueForSomeKey
都是公共的,因此根据您尝试调用它们的顺序,锁可能会以不同的顺序使用,从而导致死锁。你想干什么?这似乎是一个相当复杂的设置。我需要一种线程安全的方法从内部字典中获取值的总和。当您需要总和时,这些字典是否正在被修改?如果是,您应该使用
ConcurrentDictionary
。我正在使用.net 3.5,但无法使用.net 4(可能使用ReaderWriterLockSlim?
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();
    }
}