【问题标题】:Dictionary with lock or Concurency Dictionary?带锁的字典还是并发字典?
【发布时间】:2012-04-09 17:25:25
【问题描述】:

在多线程应用程序中首选: Dictionary 带锁对象 要么 Concurrency Dictionary

哪一种有效,我为什么要使用其中一种?

编辑 1:将 Guid 存储为键和 bool 作为值。

编辑 2:超过 2 个工作线程和一个 UI 线程。

【问题讨论】:

标签: c# .net concurrency dictionary


【解决方案1】:

我会说你有以下选择。

一些新的 Framework 4.0 类:

  • ConcurrentDictionary。工作快速可靠。
  • ConcurrentBag。它是对象的无序集合,因此运行速度更快,但适合您只需要排序的情况。
  • ConcurrentStack。它是经典 LIFO(后进先出)数据结构的实现,无需外部同步即可提供线程安全访问
  • ConcurrentQueue。这是一个线程安全的FIFO(先进先出)集合

所有新的 4.0 类运行速度更快,但具有 levanovd 提到的一些特性。这些类的性能比较你可以找到here

早期版本的一些经典解决方案:

  • 字典 + Monitor。简单换行以锁定
  • 字典 + ReaderWriterLock。比前一个更好,因为有读写锁。因此,多个线程可以读取,而只有一个线程可以写入。
  • 字典 + ReaderWriterLockSlim。只是对上一个的优化。
  • Hashtable。根据我的经验,这是最慢的方法。检查Hashtable.Synchronized() 方法,这是 Microsoft 的现成解决方案。

如果我对使用 Framework v3.5 有限制,我会使用 Dictionary + ReaderWriterLockReaderWriterLockSlim

【讨论】:

    【解决方案2】:

    仔细阅读ConcurrentDictionary。它有一些不明显的特点。

    以下是其中的一些:

    • 如果两个线程调用 AddOrUpdate,则无法保证将调用哪个工厂委托,甚至无法保证工厂委托是否会生成某个项目,该项目将存储在字典中。
    • GetEnumerator 调用获得的枚举器不是快照,可以在枚举期间修改(不会导致任何异常)。
    • KeysValues 属性是对应集合的快照,可能与实际字典状态不对应。

    所以请再次阅读ConcurrentDictionary 并确定此行为是否是您所需要的。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      我认为两者都将提供线程安全,但使用带有锁对象的 Dictionary 会将可以同时访问 Dictionary 的线程数限制为 1。使用 Concurrent Dictionary 时,您可以指定并发级别(即可以同时访问字典)。如果性能确实很重要,我相信并发字典应该是您的选择。

      【讨论】:

        【解决方案4】:

        当您使用锁定对象实现字典时,您主要关心的是线程安全。所以看起来,concurrentDictionary 已经解决了这个问题。我认为重新发明轮子是没有意义的。

        【讨论】:

        • 并非总是如此。如果速度非常重要,手动锁定可能会更好。
        • 视情况而定,您可能是对的,另一方面,没有适用于这种情况的性能数据。自定义测试可以验证性能增益(如果有)。
        • 那么这取决于你在字典中存储什么样的对象,字典的预期长度,访问字典的预期线程数,自定义锁定的实现,预期的并发访问比率,等
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 1970-01-01
        • 2015-09-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多