这个非锁定的TryGetValue()字典是否可以访问线程安全?

moo*_*oop 13 .net c# multithreading dictionary thread-safety

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题a:它是否是线程安全的?如果是,为什么?

问题b:这个双TryGetValue()模式是如何调用的?

Ree*_*sey 16

a)这不是线程安全的,因为底层Dictionary本身不是线程安全的.如果另一个线程同时调用Add,则可能发生未定义的行为.

b)这实际上是双重检查锁定的尝试.

我建议使用ConcurrentDictionary类,因为它是为这个场景设计的.另一个选择是使用ReaderWriterLockSlim(或ReaderWriterLock),如果你不是针对.NET 4.0.

  • @ csharptest.net那很苛刻; 他的推荐是"ConcurrentDictionary",这很好 - 因为Reed不是OP,**我们不知道**读者/作者的比率.我们所知道的,"ReaderWriterLockSlim"实际上可能还不错. (3认同)

csh*_*net 12

问题a:它是否是线程安全的?如果是,为什么?

它不仅不是线程安全的; 如果在另一个线程重新组织散列桶时访问它,它也会抛出NullReferenceException.锁定语句快速邪恶,不要避免它.

问题b:这个双TryGetValue()模式是如何调用的?

它被大多数人称为"虫子";)

  • *它被大多数人称为“错误”*让我大声笑;) +1 (2认同)