简体   繁体   English

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

[英]Accessing .NET dictionary in a multithreaded environment

I would like to emply the if-lock-if pattern for checking if an object is present in the dictionary in a multithreaded environment. 我想使用if-lock-if模式检查在多线程环境中字典中是否存在对象。 So, the code I am considering looks like so: 因此,我正在考虑的代码如下所示:

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;
}

I act on the assumption that even if another thread is inserting the object at the same key right now, the TryGetValue will not return a partially set reference (such thing does not exist in .NET, does it?), rather it will return null and so we enter the protected section and repeat the check. 我的假设是,即使另一个线程现在正在同一键处插入对象,TryGetValue也不会返回部分设置的引用(.NET中不存在这样的东西,对吗?),而是它将返回null。因此,我们进入受保护的部分并重复检查。

My question is my assumption correct and the code is right? 我的问题是我的假设正确,代码正确吗?

Thanks. 谢谢。

EDIT 编辑

Let me throw in a restriction. 让我施加一个限制。 The dictionary is actually a dictionary of singleton objects. 该字典实际上是单例对象的字典。 So, once an entry is occupied, it is never changed. 因此,一旦条目被占用,就永远不会改变。 Just like the Instance property of a singleton - once it is set, it is never changed. 就像单例的Instance属性一样-一旦设置,就永远不会更改。 Given that constraint, can we use the if-lock-if pattern? 在这种限制下,我们可以使用if-lock-if模式吗?

Edited for clarity: 为清楚起见进行了编辑:

No this is a very bad idea. 不,这是一个非常糟糕的主意。 You can play an if-lock game on something simple and atomic (an int ) but a Dictionary is a class with multiple moving parts. 您可以在简单的原子类( int )上玩if锁游戏,但是Dictionary是具有多个活动部分的类。 Reading and Writing must be synchronized at all times, See the ThreadSafety section on this MSDN page . 读取和写入必须始终保持同步,请参阅此MSDN页面上的ThreadSafety部分。

From http://www.yoda.arachsys.com/csharp/singleton.html : http://www.yoda.arachsys.com/csharp/singleton.html

Locking on objects which other classes can access and lock on (such as the type) risks performance issues and even deadlocks. 锁定其他类可以访问和锁定的对象(例如类型)可能会导致性能问题甚至死锁。 This is a general style preference of mine - wherever possible, only lock on objects specifically created for the purpose of locking, or which document that they are to be locked on for specific purposes (eg for waiting/pulsing a queue). 这是我的一般样式偏爱-尽可能仅锁定专门为锁定目的而创建的对象,或者出于特定目的(例如,等待/发出队列)而将其锁定在哪个文档上。 Usually such objects should be private to the class they are used in. This helps to make writing thread-safe applications significantly easier. 通常,此类对象应为使用它们的类所专用。这有助于使编写线程安全的应用程序变得更加容易。

Furthermore, double-checked locking is almost always a bad idea. 此外,双重检查锁定几乎总是一个坏主意。 Hence, I would use code similar to the following: 因此,我将使用类似于以下代码:

private static readonly object m_padlock = new object();
private IDictionary<string, SomeType> m_dic = new Dictionary<string, SomeType>();

private SomeType GetSomeObject(string key)
{
  SomeType obj;

  lock (m_padlock)
  {
    if (!m_dic.TryGetValue(key, out obj))
    {
      m_dic[key] = obj = CreateSomeObject(key);
    }
  }

  return obj;
}

See my comments to the correct reply . 请参阅我对正确回复的评论 Important part is: if you replace Dictionary to Hashtable in your example, this approach will work. 重要的部分是:如果在示例中将Dictionary to Hashtable替换为Dictionary,则此方法将起作用。

In .NET it is not possible to get partially set reference. 在.NET中,不可能获得部分设置的引用。 All read/write reference operations are atomic. 所有读/写引用操作都是原子的。

Code looks fine :) But don't forget to add synchronization to the other operations, like INSERT and UPDATE. 代码看起来不错:)但不要忘记将同步添加到其他操作,例如INSERT和UPDATE。

I think ReaderWriterLock is better than approach in this senario. 我认为ReaderWriterLock在这种情况下比方法更好。 furthermore, you have multiple readers, but only one writer. 此外,您有多个读者,但只有一个作家。

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx http://msdn.microsoft.com/zh-CN/library/system.threading.readerwriterlock.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM