[英]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.