我已经分析了我的应用程序并运行了一些性能测试,这些测试使我相信以下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);
        }
      }
    }
}

似乎比“如果锁定”或使用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()
  .....
  .....

我在这里做错了什么?

编辑:澄清一下,这种方法被平均调用超过5000万次,并且冲突通常少于5,000次。

谢谢

最佳答案

您在此处尝试做的事情完全不受支持。 TryGetValue发生在锁之外,这意味着一个线程很可能将字典写入字典,而其他线程同时调用TryGetValueDictionary<TKey, TValue>固有支持的唯一线程方案是从多个线程中读取。一旦您开始从多个线程进行读写,所有的赌注都将关闭。

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

  • 对所有对Dictionary
  • 的读取或写入访问使用单个锁
  • 使用像ConcurrentDictionary<TKey, TValue>这样的类型设计用于多线程方案。
  • 07-27 21:25