private object lockObj = new object();
private Dictionary<int, string> dict = new Dictionary<int, string>();
public string GetOrAddFromDict(int key)
{
string value;
// non-locked access:
if (dict.TryGetValue(key, out value))
return value;
lock (this.lockObj)
{
if (dict.TryGetValue(key, out value))
return value;
string newValue = "value of " + key; // place long operation here
dict.Add(key, newValue);
return newValue;
}
}
问题a:是否是线程安全的?如果是,为什么?
问题b:这个双TryGetValue()模式是如何调用的?
答案 0 :(得分:16)
a)这不是线程安全的,因为底层Dictionary
本身不是线程安全的。如果另一个线程同时调用Add,则可能发生未定义的行为。
b)这实际上是double-checked locking的尝试。
我建议使用ConcurrentDictionary类,因为它是为此场景设计的。另一个选择是使用ReaderWriterLockSlim(或ReaderWriterLock),如果你没有针对.NET 4.0。
答案 1 :(得分:11)
问题a:它是否是线程安全的?如果是,为什么?
它不仅不是线程安全的;如果在另一个线程重新组织散列桶时访问它,它也会抛出NullReferenceException。锁定语句是快速的,不要避免它。
问题b:这个双TryGetValue()模式是如何调用的?
这被大多数人称为“虫子”;)
答案 2 :(得分:2)
可悲的是,没有。
我带有一个具有此属性的自定义HashMap。
缺陷在rehash()函数中。