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

问题描述 投票:1回答:1

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

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

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

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

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

有什么替代方案可以适用于我的情况吗?

c# dictionary interlocked interlocked-increment
1个回答
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直到它消失。
© www.soinside.com 2019 - 2024. All rights reserved.