Когда ConcurrentDictionary TryRemove вернет false - PullRequest
71 голосов
/ 19 августа 2010

Будет ли возвращаться ложное значение только в том случае, если словарь не содержит значения для данного ключа или же оно также возвращает ложное значение из-за условий состязания потоков, например, когда другой поток добавляет / обновляет что-то?

Вопрос в коде:

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); 

Редактировать: Я думаю, что он вернет false только в том случае, если не содержит значения для данного ключа, но хочет быть абсолютно уверенным.

Ответы [ 3 ]

72 голосов
/ 19 августа 2010

Хотя Митч прав , что ConcurrentDictionary не уязвим к условиям гонки, я думаю, что ответ на вопрос, который вы задаете, заключается в том, что да, если ключ присутствует, TryRemove будет работатьи вернет true.

В опубликованном вами коде нет никакого способа, которым TryRemove вернул бы false, поскольку cd - локальная переменная, к которой больше нет доступа.Но если какой-то код в другом месте получил ссылку на этот объект ConcurrentDictionary и удалял ключи в отдельном потоке, то вполне возможно, что TryRemove может вернуть false, даже здесь - но только потому, что ключ былуже удалено , а не потому, что над словарем выполняется какое-то другое действие, и ключ как-то там "застрял".

6 голосов
/ 19 августа 2010

ConcurrentDictionary не подвержен условиям гонки. Вот почему вы используете его.

Возвращаемое значение

true, если объект был удален успешно; в противном случае - ложь.

1 голос
/ 07 октября 2017

Еще одно замечание:

// 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 throw. *

Параллельные коллекции имеют API-интерфейсы, которые логически объединяют эти пары test-and-do в единичные атомарные операции за единым API.

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