在多线程环境中访问.NET字典

mar*_*ark 1 .net multithreading dictionary

我想强制if-lock-if模式来检查多线程环境中字典中是否存在对象.所以,我正在考虑的代码如下:

private IDictionary<string, SomeType> m_dic = new Dictionary<string, SomeType>();

private SomeType GetSomeObject(string key)
{
  SomeType obj;
  if (!m_dic.TryGetValue(key, out obj))
  {
    lock(m_dic)
    {
      if (!m_dic.TryGetValue(key, out obj))
      {
        m_dic[key] = obj = CreateSomeObject(key);
      }
    }
  }
  return obj;
}
Run Code Online (Sandbox Code Playgroud)

我假设即使另一个线程现在正在同一个键上插入对象,TryGetValue也不会返回部分设置的引用(这样的东西在.NET中不存在,是吗?),而是返回null所以我们进入受保护的部分并重复检查.

我的问题是我的假设是正确的,代码是对的?

谢谢.

编辑

让我加入一个限制.字典实际上是单例对象的字典.因此,一旦条目被占用,它就永远不会改变.就像单例的Instance属性一样 - 一旦设置,它就永远不会改变.鉴于这种约束,我们可以使用if-lock-if模式吗?

Hen*_*man 5

编辑清晰:

不,这是一个非常糟糕的主意.你可以在简单和原子(an int)上玩if-lock游戏,但是Dictionary是一个有多个活动部分的类.必须始终同步读取和写入,请参阅此MSDN页面上的ThreadSafety部分.

  • 如果未将TryGetValue记录为线程安全,则不会定义多线程环境中的返回值.它可以是任何东西.当然,您可以查看TryGetValue的源代码并发现 - 巧合 - 它在您描述的情况下返回null.即使在这种情况下,您也不应该依赖它(请参阅"按合同设计"),因为准确的源代码可能会在未来的Framework版本中发生变化. (4认同)
  • 我知道.但我想知道,如果一个线程在另一个线程正在编写时询问(TryGetValue),它的内部状态是否会被破坏.或者,实际上已经有另一个线程插入的有效对象,返回的答案只是为空.如果状态已损坏 - 则代码错误.但是,如果TryGetValue只返回null,那么代码是正确的,因为它在受保护的部分内重复调用.请详细说明你的回复. (2认同)