【问题标题】:Cast from ConcurrentDictionary to IDictionary从 ConcurrentDictionary 转换为 IDictionary
【发布时间】:2012-04-11 18:55:14
【问题描述】:

由于 IDictionary 没有 GetOrAdd 和 AddOrUpdate 方法,从 ConcurrentDictionary 到 IDictionary 的转换是否会切断线程安全实现?

【问题讨论】:

  • 确切地说,“剪切”是什么意思?它会从ConcurrentDictionary 中删除它吗?否。它可以从IDictionary 界面获得吗?没有。
  • @JamesMichaelHare:他的意思是,如果你转换为IDictionary,它会使生成的对象线程不安全吗?也就是说,它是不是把它变成了一本普通的字典?
  • 它仍然是线程安全的吗?是的,只要没有这些操作就可以。也就是说,如果你需要一个原子的GetOrAdd(),那你就不走运了。
  • @JamesMichaelHare GetOrAdd() 不是原子的。委托在内部锁之外执行以防止死锁。见msdn.microsoft.com/en-us/library/dd997369.aspx
  • @mikez:是的,对不起,原子是错误的选择。我的错。我的意思是说,如果实际的 Add() 不存在,它将被同步,因此只有一个竞争对手实际执行 Add(),但正如您从 MSDN 正确指出的那样,多个同时调用者可能会执行委托并最终生成被忽略的不需要的项目。

标签: c# .net concurrency thread-safety


【解决方案1】:

生成的对象仍将是并发字典。 Add 或 Remove 之类的调用使用底层实现 TryAdd 和 TryRemove(它们是线程安全的)。将对象转换为不同的类型不会改变对象本身。

此外,为了澄清起见,您可以使用 ILSpy 之类的工具来查看默认 IDictionary 方法的实现是什么,以及它们是否仍然是线程安全的。

【讨论】:

【解决方案2】:

IDictionary 只是一个接口。如果你强制转换它,结果是 ConcurrentDictionary 的实现,缺少 GetOrAddAddOrUpdate 方法。

大概,您仍然可以使用Item 属性和AddContainsKey 方法(代替GetOrAddAddOrUpdate)方法,并且您的转换对象仍然是线程安全的(因为底层实现是ConcurrentDictionary)。

【讨论】:

    【解决方案3】:

    接口不影响实现。它只是没有暴露ConcurrentDictionary 的一些方法。

    您可能会发现thisthis 有助于理解接口。

    【讨论】:

      【解决方案4】:

      这就像通过IDictionary 形状的钥匙孔看着大的ConcurrentDictionary 对象 - 你只能看到IDictionary 形状,但它仍然是ConcurrentDictionary

      【讨论】:

        【解决方案5】:

        简答否。

        您正在通过接口操作对象,因此仍在使用具体实现。您不会丢失任何功能或其方法。它们只是不可用。

        附带说明,向下转换时需要显式转换,向上转换时不需要显式转换 - 这样做总是安全的。

        【讨论】:

        • sorry 但是 ConcurrentDictionary 添加了两个新方法并隐藏了其他方法,因此它的实现只能为新方法添加线程安全,而不是为隐藏的方法添加线程安全。 MSDN 文档没有说明,所以我问了。但是在我阅读了最好的 cmets 并查看了 ConcurrentDictionary 原型之后,我看到了它没有扩展 Dictionary 的内容,这让我放心,将其转换为 IDictionary 不太可能间接使用扩展版本的 Dictionary。
        猜你喜欢
        • 1970-01-01
        • 2017-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 1970-01-01
        相关资源
        最近更新 更多