锁定字典的TryGetValue() - 性能问题

Had*_*adi 6 c# performance dictionary locking

我已经分析了我的应用程序并运行了一些性能测试,这使我相信以下if-lock-if安排:

private float GetValue(int id)
{
    float value;
    if (!dictionary.TryGetValue(id, out value))
    {
      lock (lockObj)
      {
        if (!dictionary.TryGetValue(id, out value))
        {
          value = ComputeValue(id);
          dictionary.Add(id, value);
        }
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎比"lock-if"或使用ReaderWriterLockSlim执行得更快.但很少,我得到以下异常:

1) Exception Information
*********************************************
Exception Type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Data: System.Collections.ListDictionaryInternal
TargetSite: Int32 FindEntry(TKey)
HelpLink: NULL
Source: mscorlib

StackTrace Information
*********************************************
  at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
  at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
  at MyNamespace.GetValue()
  .....
  .....
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?

编辑:澄清一下,这种方法的平均调用次数超过5000万次,冲突一般不到5000次.

谢谢

Jar*_*Par 15

你在这里尝试做的只是不支持的场景.该TryGetValue这就意味着很可能就是一个线程被写入字典,而其他同时调用锁之外发生TryGetValue.唯一支持的线程方案Dictionary<TKey, TValue>是从多个线程读取.一旦你开始从多个线程读取和写入,所有的赌注都会被取消.

为了确保安全,您应该执行以下操作之一

  • 使用单个锁对所有读取或写入访问 Dictionary
  • 使用类似于ConcurrentDictionary<TKey, TValue>多线程方案的类型.

  • 是的,他需要使用'ConcurrentDictionary'确保+1 (3认同)