C# - 像列表一样的字典上的互锁增量

时间:2018-03-10 00:04:32

标签: c# dictionary interlocked interlocked-increment

我知道int在内存中没有固定的位置所以它根本无法像那样工作。 但完全相同的代码部分将与不同的名称,参数e.t.c

同时运行

我需要传递一个“Name”字符串,然后以某种方式递增我的int数组中的一个项目。

Dictionary<string, int> intStats = new Dictionary<string, int>();

此词典根据作为词典字符串键提供的“名称”存储所有统计信息。

由于我使用了大量的多线程,我希望尽可能保持int count的同步。这就是我尝试使用Interlocked.Increment(ref intStats[theName]);的原因 但不幸的是,这不会奏效。

有没有其他方法适用于我的情况?

1 个答案:

答案 0 :(得分:2)

首先,我建议创建一个捕获抽象数据类型语义的自定义类型。这样,您就可以尝试不同的实现,这样您的呼叫网站就可以自我记录。

internal sealed class NameCounter
{
  public int GetCount(string Name) { ... }
  public void Increment(string Name) { ... }
}

那么:鉴于这必须是线程安全的,你可以做出哪些实现选择?

  • 私有Dictionary<string, int>会起作用,但您必须在每次访问时锁定字典,这可能会变得昂贵。

  • 私有ConcurrentDictionary<string, int>,但请注意,您必须在循环中使用TryUpdate ,以确保不会丢失值。

  • 制作包装类型:

internal sealed class MutableInt
{
  public int Value;
}

这是您想要创建公共字段的极少数情况之一。现在创建一个ConcurrentDictionary<string, MutableInt>,然后InterlockedIncrement公共字段。现在你没有TryUpdate,但这里仍然有一场比赛:如果两个线程都试图在第一次同时添加相同的名称那么你必须确保他们中只有一人获胜。请谨慎使用AddOrUpdate以确保此次比赛不会发生。

  • 将您自己的并发字典实现为索引为int数组的哈希表;关于数组元素的InterlockedIncrement。同样,在系统中引入新名称时,您必须非常小心,以确保以线程安全的方式检测到哈希冲突。

  • 将字符串哈希到n个存储桶中的一个,但这次存储桶是不可变字典。每个桶都有一个锁;锁定桶,从旧桶中创建一个新词典,将其放回桶中,解锁桶。如果存在争用,请增加n直到它消失。