【问题标题】:How to update two dictionaries concurrently如何同时更新两个字典
【发布时间】:2012-12-10 09:06:54
【问题描述】:

我需要支持更新两个并发字典的功能(创建、更新、删除)。 每个操作(更新、删除、创建)使用其中的两个并且应该是原子的。在 .NET C# 中执行此操作的最佳方法是什么。

【问题讨论】:

  • 当您说“并发词典”时,您指的是什么类?
  • System.Collections.Concurrent.ConcurrentDictionary

标签: .net c#-4.0 concurrency thread-safety


【解决方案1】:

最简单的方法是使用锁:

private object m_methodMonitor = new object();

private void Update()
{
    lock (m_methodMonitor)
    {
        // Do whatever
    }
}


private void Delete()
{
    lock (m_methodMonitor)
    {
        // Do whatever
    }
}

请注意:锁定字典上的“写入”操作是不够的!您还需要同步对字典的读取,以避免尝试从字典中获取值时出现这种情况,该值当前正被一种更新方法访问。

【讨论】:

  • 每个键的锁定机制如何?
  • 应该注意的是,要使此功能在您访问字典实例的任何地方都起作用,您必须在类似的lock 语句中这样做,而不仅仅是列出的三个操作。
  • @user547297:不可能锁定每个键 - 也没有必要。与在插入/更新/删除所需的短时间内锁定整个字典相比,实现锁定字典中单个条目的开销会更多。
  • 我不明白你为什么需要使用两个锁?此外,每当您使用两个锁时,如果您沿着两条代码路径尝试以不同的顺序获取锁,您就会面临死锁的风险。
  • -1 用于使用两个锁。这在这里既危险又不必要!
【解决方案2】:

这里的挑战是要求两个字典都必须原子地修改ConcurrentDictionary<TKey,TValue> 类没有任何内置机制来支持将实例“分组”在一起以允许同时更新共享相同键的键值对。

因此,您无法使用任何高吞吐量机制来授予您操作中的原子性。

要对一组对象进行原子操作,您唯一能做的就是将对对象的访问封装在锁定机制中:

public void Update(...)
{
    lock(this.dictionaryLock)
    {
        this.dictionaryA.AddOrUpdate(...);
        this.dictionaryB.AddOrUpdate(...);
    }
}

使用不同的锁定机制可能会获得更好的结果,优化到应用程序的常见模式(例如,如果您的应用程序倾向于频繁读取和不经常修改,则使用 ReaderWriterLockSlim),但您只能序列化对整个应用程序的访问字典。

如果并发性能对您非常重要,您必须重构您的设计以使用单个并发字典而不是两个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 2013-04-30
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多