Когда ConcurrentDictionary TryRemove вернет false
Будет ли он возвращать false только в том случае, если словарь не содержит значения для данного ключа или он также будет возвращать false из-за условий гонки нитей, например, другой поток добавляет/обновляет что-то?
Вопрос в коде:
ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>();
// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one");
// Will this ever fail if no other thread ever removes with the key value of 1?
cd.TryRemove(1);
Edit:
Я думаю, что он вернет false только в том случае, если он не содержит значения для данного ключа, но должен быть абсолютно уверен.
Ответы
Ответ 1
В то время как Митч прав, что ConcurrentDictionary
не уязвим для условий гонки, я думаю, что ответ на вопрос, который вы задаете, заключается в том, что да, если ключ присутствует, TryRemove
будет работать и вернет true
.
В коде, который вы отправили, нет способа вернуть TryRemove
false
, поскольку cd
- это локальная переменная, не доступная нигде. Но если какой-то код в другом месте был дан ссылкой на этот объект ConcurrentDictionary
и удалял ключи в отдельном потоке, тогда возможно, что TryRemove
может возвращать false
, даже здесь, но только потому, что ключ был уже удален, а не потому, что в словаре выполняется какое-то другое действие, и ключ каким-то образом "застревает" там.
Ответ 2
ConcurrentDictionary не страдает от условий гонки. Вот почему вы его используете.
Возвращаемое значение
true, если объект удален успешно; в противном случае - false.
Ответ 3
Еще один момент:
// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one");
Этот комментарий неверен и, возможно, страдает от того же неправильного представления о том, что значит "попробовать". Это не о параллельной попытке добавить, то ли значение уже было добавлено с помощью клавиши 1
.
Рассмотрим стандарт Dictionary<TKey,TValue>
. Эквивалентным кодом будет:
if (!d.Contains(1))
d.Add(1, "one");
Для этого требуется две операции. Нет никакого способа создать такой API, чтобы быть потокобезопасным, поскольку cd
может иметь значение с ключом 1
, добавленным между вызовом Contains
и Add
, которое затем приведет к металокации Add
.
В параллельных коллекциях есть API-интерфейсы, которые логически объединяют эти тестовые пары в одиночные атомные операции за одним API.