c# - 双重检查字典 "ContainsKey"上的锁定

标签 c# multithreading collections dictionary double-checked-locking

我的团队目前正在讨论这个问题。

有问题的代码是

if (!myDictionary.ContainsKey(key))
{
    lock (_SyncObject)
    {
        if (!myDictionary.ContainsKey(key))
        {
            myDictionary.Add(key,value);
        }
    }
}

我看到的一些帖子说这可能是一个很大的 NO NO(当使用 TryGetValue 时)。然而,我们团队的成员说这没问题,因为“ContainsKey”不会迭代 key 集合,而是通过 O(1) 中的哈希码检查 key 是否包含在内。因此他们声称这里没有危险。

我想听听您对这个问题的诚实意见。

最佳答案

不要这样做。这不安全。

您可能正在调用 ContainsKey来自一个线程,而另一个线程调用 Add . Dictionary<TKey, TValue> 根本不支持这一点.如果Add需要重新分配存储桶等,我可以想象您可能得到一些非常奇怪的结果或异常。它可能是以您看不到任何不良影响的方式编写的,但我不想依赖它。

使用双重检查锁定对字段进行简单的读/写是一回事,尽管我仍然反对它 - 调用已明确描述为 不是 对多个并发调用是安全的。

如果您使用的是 .NET 4, ConcurrentDictionary 可能是前进的方向。否则,只需锁定每次访问即可。

关于c# - 双重检查字典 "ContainsKey"上的锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6018768/

相关文章:

C#线程使用调用,卡住表单

c# - WPF 中的线程问题

c++ - 在没有事件异常的情况下调用线程终止

java - 在同一 arraylist 上使用 addall 和 removeall 的并发修改异常

c# - LINQ C# 集合中的唯一元素

C# 加速字符串?

c# - Asp.Net 5 Mvc 6 依赖注入(inject) : Register for Session

c# - 删除对对象的引用时结束线程

collections - 扩展 VecDeque 以限制大小

C#:从文本框转换(识别)数学公式