【问题标题】:Is ConcurrentDictionary ContainsKey method synched?ConcurrentDictionary ContainsKey 方法是否同步?
【发布时间】:2014-08-20 00:19:33
【问题描述】:

简单的问题 假设我有一个ConcurrentDictionary

我使用TryAddContainsKey 方法

现在假设我从 100 个线程开始处理东西。假设当 3 个线程使用 TryAdd 方法添加新密钥时,另外 3 个线程使用 ContainsKey 方法询问密钥是否存在

ContainsKey 是否在返回结果之前等待这 3 个线程添加进程?

或者它们没有同步,我的意思是这 3 个线程之一可能正在添加我使用 ContainsKey 方法询问的密钥,但是由于该过程尚未完成,我将得到的答案将是错误的

非常感谢 C# WPF .net 4.5 最新的答案

【问题讨论】:

    标签: c# multithreading concurrentdictionary


    【解决方案1】:

    “否”(参见 Sam 的评论),此外ContainsKey 在对 ConcurrentDictionary 的其他访问或方法调用中建立了no原子保护。

    也就是下面的代码坏了

    // There is no guarantee the ContainsKey will run before/after
    // different methods (eg. TryAdd) or that the ContainsKey and another
    // method invoked later (eg. Add) will be executed as an atomic unit.
    if (!cd.ContainsKey("x")) {
      cd.Add("x", y);
    }
    

    并且应该一致地使用Try* 方法

    cd.TryAdd("x", y);
    

    如果需要通过专门的并发方法来保证进一步的同步(或原子性),则应建立更大的监视器/锁定上下文。

    【讨论】:

    • -1:我将问题解释为粗体字为“ContainsKey 是否包含同步调用,这将导致它等到对TryAdd 的调用完成后再返回答案?”这个问题的答案是“不”。并发集合与使用锁定进行同步的集合非常不同。他们尽可能避免锁定,通常使用lock-free or wait-free algorithms
    • @280Z28 很好的观察。我已经更新了关于评论的初始措辞。此外,作为支持推理,ContainsKey 在内部使用 TryGetValue(参考 ConcurrentDictionary.cs from grepcode)。
    • 我删除了我的 -1 票,但因为它被引用,所以保留了评论。这是一个更好的链接:referencesource.microsoft.com/#mscorlib/system/Collections/…
    • 如果您指望 containsKey 来告诉您该密钥是否存在于可能以前删除的密钥中,那么即使 TryAdd 也可能会失败。 concurrentdictionary 进入它认为键不存在的状态,无论是否存在,它都无法添加相同的键。这似乎非常糟糕。
    • @nixkuroi 但是,ConcurrentDictionary 的内部状态在任何时候都不会损坏。应检查 TryAdd 的结果以确保是否添加了特定键;任何更大的原子上下文都必须通过其他方式来保护,例如锁。)
    猜你喜欢
    • 2012-03-13
    • 2012-05-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2018-04-30
    • 2012-03-20
    • 2012-04-19
    相关资源
    最近更新 更多