Коли ConcurrentDictionary TryRemove поверне false


79

Чи поверне він значення 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); 

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

Відповіді:


85

Хоча Мітч має рацію, що а ConcurrentDictionaryне є вразливим до расових умов, я думаю, що відповідь на ваше запитання полягає в тому, що так, якщо ключ присутній, TryRemoveспрацює і повернеться true.

У коді, який ви опублікували, немає способу, який TryRemoveби повернувся, falseоскільки cdлокальна змінна не доступна ніде більше. Але якщо якийсь інший код отримував посилання на цей ConcurrentDictionaryоб’єкт і видаляв ключі в окремому потоці, можливо, він TryRemoveможе повернутися falseнавіть тут - але лише тому, що ключ уже був вилучений , а не тому, що на словник і ключ там якось "застрягли".


5

ConcurrentDictionary не страждає від умов гонки. Тому ви ним користуєтесь.

Повернене значення

true, якщо об’єкт було видалено успішно; інакше, помилково.


2

Ще один момент, на який слід звернути увагу:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.