字典查找需要锁定吗?

时间:2010-10-22 19:38:46

标签: c# multithreading dictionary locking lookup

lock(dictionaryX)
{
   dictionaryX.TryGetValue(key, out value);
}
在对字典进行查找时,

是否需要锁定?

该程序是多线程的,并且在向dict添加键/值时。 dict被锁定了。

9 个答案:

答案 0 :(得分:11)

如上所述here

  

使用TryGetValue()而不锁定是不安全的。字典暂时处于使其不适合阅读而另一个线程正在编写字典的状态。随着包含的条目数量的增加,字典将不时重新组织。当您在重新组织发生的确切时间进行读取时,在存储桶更新但尚未输入值时,您将面临发现密钥错误值的风险。

更新: 看看this page的“线程安全”部分。

答案 1 :(得分:4)

与编程中的许多微妙问题一样,答案是:不一定。

如果仅将值添加为初始化,则无需同步后续读取。但是,另一方面,如果您要随时阅读和写作,那么绝对需要保护该资源。

然而,完整的lock可能不是最好的方式,具体取决于您的词典获得的流量。如果您使用的是.NET 3.5或更高版本,请尝试ReaderWriterLockSlim

答案 2 :(得分:3)

如果您有多个线程访问Dictionary,那么您需要锁定更新和查找。您需要锁定查找的原因是,在您执行查找的同时可能会发生更新,并且在更新期间字典可能处于不一致状态。例如,假设您有一个线程执行此操作:

if (myDictionary.TryGetValue(key, out value))
{
}

并且一个单独的线程正在执行此操作:

myDictionary.Remove(key);

可能发生的是,执行TryGetValue的线程确定该项目在字典中,但在它可以检索项目之前,另一个线程将其删除。结果是执行查找的线程会抛出异常,或TryGetValue将返回truevalue将是null或可能是不匹配的对象关键。

这只会发生一件事。如果您在一个线程上执行查找而另一个线程添加了您尝试查找的值,则会发生类似灾难性的事情。

答案 3 :(得分:2)

只有在线程之间同步对资源的访问时才需要锁定。只要没有涉及多个线程,就不需要锁定。

在更新和读取多个线程的值的上下文中,是的,绝对需要锁定。实际上,如果您使用的是4.0,则应考虑切换到专门为并发访问而设计的其中一个集合。

答案 4 :(得分:2)

使用new ConcurrentDictionary<TKey, TValue> object,您可以忘记必须进行任何锁定。

答案 5 :(得分:1)

是的,您需要锁定字典以便在多线程环境中进行访问。写入字典不是原子的,因此它可以添加键,但不能添加值。在这种情况下,当您访问它时,您可能会遇到异常。

答案 6 :(得分:1)

如果您使用.Net 4,则可以使用ConcurrentDictionary替换以安全地执行此操作。在System.Collection.Concurrent namespace中,当您需要多线程访问时,还有其他类似的集合。

如果这是您的选择,请不要使用自己动手锁定。

答案 7 :(得分:0)

是的,如果此字典是多个线程之间的共享资源,则应锁定。这可以确保您获得正确的值,而其他线程不会在您的Lookup调用期间中途改变值。

答案 8 :(得分:0)

是的,如果您对该字典有多线程更新,则必须锁定。查看这篇精彩帖子了解详情:“Thread safe” Dictionary(TKey,TValue)

但是自ConcurrentDictionary<>引入以来,您可以通过.NET 4或3.5中的Rx使用它(它包含System.Threading.dll以及新线程安全集合的实现)