【问题标题】:HashTable concurrency哈希表并发
【发布时间】:2012-02-22 01:40:50
【问题描述】:

我有一个可以被多个线程访问的 HashTable。例如让我们看三个线程:

线程 A 做 Hash.Insert("a",new object());

线程 B 做 Hash.Insert("b",new object());

线程 C 做 Hash.Insert("a",new object());

由于某些原因,我不能对整个哈希使用锁定

我不关心顺序或在流程结束时哪个对象将位于散列中。我唯一关心的是不会因为从不同线程更新同一个单元格而导致数据损坏。

我有哪些选择?或者这不是问题,HashTable 自己处理并保持数据完整。

【问题讨论】:

  • “由于某些原因,我不能在整个哈希上使用锁” 你能解释一下这个要求吗?只是性能吗?
  • @CodeInChaos 可能同时有数千个请求,所以我更担心饥饿,因为它可能获得锁的线程永远不会获得处理器时间......
  • 由于锁的非 FIFO 处理,您极不可能遇到饥饿。见stackoverflow.com/questions/961869/…。用于保证 FIFO 排序的同步对象,这将防止饥饿。

标签: .net multithreading concurrency hashtable


【解决方案1】:

你可以考虑使用类似的东西:

ConcurrentDictionary<string, object> Hash = new ConcurrentDictionary<string, object>();

来自 System.Collections.Concurrent 命名空间。

【讨论】:

  • 我想过,但这取决于 ConcurrentDictionary 是如何实现的。它会锁定整个哈希吗?还是更复杂?
  • @Amit 我很确定实现是无锁的,但这当然只是一个实现细节。但是没有办法直接观察无锁和锁定实现之间的区别,除了无锁通常更快。
  • 从反射器的快速浏览来看,并发字典似乎使用了桶锁,并且它似乎有几个锁,每个单元格的数量都有一个锁。希望它足够好
【解决方案2】:

ConcurrentDictionary 应该适合您。它不是无锁的,但它不会“锁定整个哈希”,除非在某些情况下。

它使用两个集合,一个锁数组和一个哈希桶集合。
锁桶的数量可以通过设置并发级别来控制,哈希桶的初始数量可以通过设置初始容量来控制。 (这些都是构造函数参数)。

锁数组中的每个存储桶使用一个简单的模散列覆盖多个(实际上至少是一个)散列存储桶。

并发字典锁定所有锁桶的唯一时间是:

  1. 调整哈希存储桶的大小时。
  2. 读取公共密钥属性时。
  3. 读取公共 Values 属性时。
  4. 读取公共 Count 属性时。
  5. 读取公共 IsEmpty 属性时。
  6. 调用 Clear() 时。
  7. 序列化时。

除了调整大小之外,这些都是很容易避免的。

如果您可以预测字典中的最大项目数,则可以避免调整大小。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2013-03-30
    相关资源
    最近更新 更多