在一个线程中调用Add on SortedDictionary并在另一个线程中获取Item是否安全?

时间:2013-07-17 14:12:24

标签: c# .net multithreading dictionary locking

我正在努力使我的SortedDictionary线程安全,而我不确定的是:在一个线程中调用添加到SortedDictionary是否安全,如下所示:

dictionary.Add(key, value);

并在另一个线程中从这个字典中获取一个项目,如下所示:

variable = dictionary[key];

这两个地方都没有明确的枚举,所以它看起来很安全,但要确定它是很好的。

4 个答案:

答案 0 :(得分:1)

不,同时读取和写入SortedDictionary<K,V>是不安全的:向排序字典添加元素可能涉及树的重新平衡,这可能导致并行读取操作在导航时出错感兴趣的元素。

为了解决这个问题,您需要在执行显式锁定的类中包装SortedDictionary<K,V>的实例,或者使用与SortedDictionary<K,V>实现的接口兼容的滚动自己的集合。

答案 1 :(得分:1)

没有。修改树的任何东西都不是线程安全的。诀窍是在一个线程中填充SortedDictionary,然后将其视为不可变,并让多个线程从中读取。 (您可以使用SortedDictionary执行此操作,如here所述。我提到这一点是因为可能有一个集合/字典/地图在某处被读取时会被更改,因此您应该始终检查。)

如果你需要修改它,一旦它被释放到野外,你就会遇到问题。你需要锁定它来写入它,并且所有读者都需要尊重这个锁,这意味着他们也需要锁定它,这意味着读者不能再同时读取它。 围绕此的最佳方法通常是创建一个全新的SortedDictionary,然后,一旦新的SortedDictionary不可变,将引用替换为对原始引用的引用。 (你需要一个易变的参考来做到这一点。)读者将干净地切换字典没有问题。在最后一位读者完成阅读并发布其参考资料之前,旧词典不会消失。

(有n个读者和1个作家锁,但你想要避免任何锁定。)

(请记住,如果你要枚举,对字典的引用会突然改变。使用局部变量而不是引用(volatile)引用。)

Java有一个ConcurrentSkipListMap,允许任意数量的同时读写,但我认为.NET中还没有类似的东西。如果有,那么读取的速度要比不可变的SortedDictionary慢。

答案 2 :(得分:1)

不,因为记录是安全的。这才是真正的原因。实施细节的推理不是很好,因为它们是您不能依赖的细节

答案 3 :(得分:0)

不,这样做是不安全的。如果你想在多线程中实现而不是你应该这样做

 private readonly object lockObject = new object();
 lock (lockObject )
    {
        //your dictionary operation here.
    }