ConcurrentDictionary с несколькими значениями для каждого ключа, удаление пустых записейC#

Место общения программистов C#
Ответить
Anonymous
 ConcurrentDictionary с несколькими значениями для каждого ключа, удаление пустых записей

Сообщение Anonymous »

ConcurrentDictionary хорошо работает в одновременных ситуациях, когда каждый ключ сопоставляется с одним значением. При сопоставлении с несколькими значениями легко создать ConcurrentDictionary и защитить его функции добавления/удаления.

Код: Выделить всё

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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»