Код: Выделить всё
ConcurrentDictionary d;
// Add
var list = d.GetOrAdd ("key", x => new List ());
lock (list) {
list.Add ("value to add");
}
// Remove
if (d.TryGetValue ("key", out var list)) {
lock (list) {
list.Remove ("value to remove");
}
}
Код: Выделить всё
if (d.TryGetValue ("key", out var list)) {
lock (list) {
if (list.Remove ("value to remove") && list.Count == 0) {
d.TryRemove ("key", out _);
}
}
}
- A: получить список
- B: получить список
- B: заблокировать, удалить из списка< /li>
B: список пуст, удалить ключ, разблокировать - A: заблокировать, добавить в список, разблокировать
Насколько я могу судить, решение обычно находится с использованием операций сравнения и замены и замены списка, например. неизменяемый массив, который затем заменяется полностью. Однако, учитывая, что ConcurrentDictionary не предлагает TryRemove с ожидаемым значением для сравнения, я не совсем понимаю, как это сделать. Возможно, существует двухэтапное решение?
Использование параметра out TryRemove для повторного добавления значений после их удаления (для устранения случаев гонки) невозможно. - словарь кратковременно будет находиться в несогласованном состоянии.
На этом сайте много вопросов о подобных сценариях, но большинство из них страдают от тривиальных ошибок или не удаляются пустые записи. Существует очень связанный с этим вопрос, который спрашивает, возможно ли это сделать. К сожалению, ему пять лет, ему уделяется очень мало внимания, и у него нет другого решения, кроме использования блокировок (что противоречит цели). Возможно, с того времени открылся лучший путь.
(Отредактированный пример для ясности)
Подробнее здесь: https://stackoverflow.com/questions/606 ... ty-entries
Мобильная версия