C#.NET 4.0 ConcurrentDictionary: TryRemove в блокировке?

Я полагаю, что это работает, я протестировал его с несколькими параллельными потоками (хотя не исчерпывающе для условий состязания и мертвых блокировок):

public static System.Collections.Concurrent.ConcurrentDictionary dict =
        new System.Collections.Concurrent.ConcurrentDictionary();
public static item dump;

...

foreach (System.Collections.Generic.KeyValuePair x in dict)
{
    lock (x.Value)
    {
        if (x.Value.IsCompleted)
        {
            dict.TryRemove(x.Key, out dump);
        }
    }
}

Этим вопросом является вид продолжения этого вопроса:

Я могу удалить объекты из ConcurrentDictionary из цикла перечисления того словаря?

И этот вопрос:

Обновление полей значений в ConcurrentDictionary

В этом я делаю два "рискованных" маневра:

  1. Удаление значений от a ConcurrentDictionary одновременно перечисляя через него (который, кажется, в порядке).
  2. Блокировка Value часть a ConcurrentDictionary. Необходимый, потому что управление полями значения не ориентировано на многопотоковое исполнение, только управляя самими значениями ConcurrentDictionary ориентировано на многопотоковое исполнение (код выше является отрывком большего блока кода, в котором полями значений на самом деле управляют).

5
задан Community 23 May 2017 в 12:18
поделиться

1 ответ

Удаление значений из параллельного словаря во время итерации по нему - это нормально. Это может иметь некоторые последствия для производительности (я не уверен), но это должно работать.

Обратите внимание, что вы не блокируете что-то внутреннее в ConcurrentDictionary - вы блокируете монитор, связанный с объектом item. Я бы лично не хотел этого делать: либо эти элементы должны быть потокобезопасными (что позволяет манипулировать ими в любом случае), либо (предпочтительнее) неизменяемыми, чтобы вы могли наблюдать их из любого потока без блокировки. Или вы можете просто сделать отдельное свойство, которое вы проверяете, потокобезопасным, конечно. Документируйте все, что вы делаете!

Наконец, ваше использование out dump кажется несколько сомнительным. Смысл в том, чтобы было что передать TryRemove? Если да, то я бы использовал локальную переменную вместо статической.

4
ответ дан 15 December 2019 в 00:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: