【发布时间】:2010-10-11 23:22:22
【问题描述】:
我想知道锁定 List<T>、HashSet<T> 或 Dictionary<TKey, TValue> 等集合而不是简单的 object 是否有任何缺点。
注意:在以下示例中,这是唯一发生锁的地方,它不是从多个位置锁定的,而是可以从多个线程调用静态方法。此外,_dict 永远不会在 GetSomething 方法之外访问。
我当前的代码如下所示:
private static readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
public static string GetSomething(string key)
{
string result;
if (!_dict.TryGetValue(key, out result))
{
lock (_dict)
{
if (!_dict.TryGetValue(key, out result))
{
_dict[key] = result = CalculateSomethingExpensive(key);
}
}
}
return result;
}
另一位开发人员告诉我锁定集合会导致问题,但我对此表示怀疑。如果我这样做,我的代码会更有效率吗?
private static readonly Dictionary<string, string> _dict = new Dictionary<string, string>();
private static readonly object _syncRoot = new object();
public static string GetSomething(string key)
{
string result;
if (!_dict.TryGetValue(key, out result))
{
lock (_syncRoot)
{
if (!_dict.TryGetValue(key, out result))
{
_dict[key] = result = CalculateSomethingExpensive(key);
}
}
}
return result;
}
【问题讨论】:
-
您是否考虑将 _dict 和 GetSomething() 移到单独的类中?它显然做了一些与班级其他人不同且无关的事情。 (它看起来像一个记忆模式)
-
您必须将 _dict 声明为 volatile 才能有机会正确处理。另请参阅有关双重检查锁定及其陷阱的答案:stackoverflow.com/questions/394898/…
-
@Sjoerd volatile 在许多情况下对 C# 进行双重检查是不必要的。但是,这里的双重检查不起作用,因为它不是双重检查字段读取而是双重检查方法调用,它仅在调用的方法是原子的情况下才有效,这不是,所以双重检查这里完全错了。
-
@Jon Hanna True。这显示了双重检查锁定有多少陷阱。
-
@Sjoerd,是的。我通常认为它是一种优化而不是“正常”技术,但是有时可以通过做通常被认为是优化的事情来减轻死锁的风险!尽管如此,仔细检查总是可疑的,在这种情况下非常危险,以至于我的答案花在这上面的时间比其他任何事情都多。
标签: c# .net multithreading locking