Многоуровневый ConcurrentDictionary по-прежнему потокобезопасен? - PullRequest
4 голосов
/ 09 февраля 2011

У меня есть четырехуровневая структура данных, определенная так:

Dictionary<Type1, Dictionary<Type2, Dictionary<Type3, List<Type4>>>>

Все это заключено в класс, который также поддерживает безопасность потоков. В настоящее время он просто блокирует всю коллекцию, пока читает / манипулирует данными (чтение на порядок чаще, чем запись).

Я думал о замене Dictionary на ConcurrentDictionary и List на ConcurrentBag (его элементы не нужно заказывать).

Если я это сделаю, могу ли я просто устранить блокировки и быть уверенным, что одновременные коллекции будут работать правильно?

Ответы [ 2 ]

6 голосов
/ 12 декабря 2011

Я почти на год опоздал на этот вопрос ... но на всякий случай, если кто-нибудь окажется в положении, аналогичном Матею Забскому, спросите себя:

Можете ли вы использовать Dictionary<Tuple<Type1, Type2, Type3>, List<Type4>> вместо?

Значительно проще работать, и, учитывая, что хеш-таблицы (т.е. словари) являются O (1) структурами данных с несколько большим постоянным компонентом (даже более того, если вы перейдете на ConcurrentDictionary), он, вероятно, будет работать быстрее тоже. Он также использовал бы меньше памяти и был бы довольно тривиален для преобразования в ConcurrentDictionary.

Конечно, если вам нужно перечислить все данные Type2 для данного ключа Type1, возможно, вам пригодятся вложенные словари. Но является ли это требованием?

4 голосов
/ 09 февраля 2011

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

Возвращенный из словаря перечислитель безопасен для одновременного использования с операциями чтенияи записывает в словарь, однако он не представляет моментальный снимок словаря.Содержимое, предоставляемое через перечислитель, может содержать изменения, внесенные в словарь после вызова GetEnumerator.

Если вы хотите сохранить точное поведение, которое у вас сейчас, но при этом сэкономить на стоимости блокировки, вы можете захотетьблокировать с помощью ReaderWriterLockSlim , что особенно подходит для случаев с большим количеством операций чтения, чем операций записи.

...