Является ли этот неблокированный доступ к словарю TryGetValue () потокобезопасным? - PullRequest
12 голосов
/ 18 июля 2011
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;
    }
}

Вопрос а: Это потокобезопасно? Если да, то почему?

Вопрос b: Как вызывается этот шаблон double-TryGetValue ()?

Ответы [ 3 ]

16 голосов
/ 18 июля 2011

a) Это не потокобезопасно, так как сам базовый Dictionary не является потокобезопасным. Если другой поток вызывает Add одновременно, может возникнуть неопределенное поведение.

b) Это фактически попытка двойной проверки блокировки .

Я бы рекомендовал вместо этого использовать класс ConcurrentDictionary , так как он предназначен для этого сценария. Другой вариант - использовать ReaderWriterLockSlim (или ReaderWriterLock ), если вы не нацелены на .NET 4.0.

11 голосов
/ 19 июля 2011

Вопрос а: Потокобезопасен? Если да, то почему?

Мало того, что это не потокобезопасный; он также генерирует исключение NullReferenceException, если к нему обращаются, когда другой поток реорганизует хэш-блоки. Оператор блокировки работает быстро, не избегайте его.

Вопрос b: как вызывается этот шаблон с двойным TryGetValue ()?

Большинство людей называют это "ошибкой";)

2 голосов
/ 18 июля 2011

К сожалению, нет.

Я ношу с собой пользовательский HashMap с этим свойством.

Дефект в функции rehash ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...