Является ли запрос linq к ConcurrentDictionary Values потокобезопасным?
Допустим, у меня есть следующий код:
ConcurrentDictionary<long, long> myDict= new ConcurrentDictionary<long, long>();
Обычно каждый доступ по ключу является потокобезопасным, но является ли следующий запрос linq потокобезопасным? Я не нашел ничего в документации: http://msdn.microsoft.com/en-us/library/dd287226.aspx
if myDict.Values.Any(x => !x.HasPaid))
{
return false
}
4 ответа
Исправление... Я не уверен, когда вы получаете доступ к свойству Значения. Потокобезопасен при использовании LINQ для самого объекта.
LINQ будет использовать метод GetEnumerator для итерации элементов.
Прямо из MSDN
Перечислитель, возвращаемый из словаря, безопасен для одновременного чтения и записи в словарь, однако он не представляет моментальный снимок словаря. Содержимое, предоставляемое через перечислитель, может содержать изменения, внесенные в словарь после вызова GetEnumerator.
if myDict.Any(x => !x.Value.HasPaid))
{
return false
}
Как уже упоминалось, ConcurrentDictionary.GetEnumerator() не представляет моментальный снимок словаря. Однако ConcurrentDictionary.Values создает моментальный снимок времени.
Поэтому следующие не эквивалентны:
myDict.Any(x => !x.Value.HasPaid)
myDict.Values.Any(x => !x.HasPaid)
Документация состояний ConcurrentDictionary ( MSDN):
Все открытые и защищенные члены ConcurrentDictionary являются поточно-ориентированными и могут использоваться одновременно из нескольких потоков.
Поскольку свойство.Values является реализацией, продиктованной интерфейсом IColletion, оно является открытым и, следовательно, потокобезопасным.
Все ответы до сих пор великолепны и полезны, но я думаю, что ссылка, которую DuneCat указал в одном из комментариев, подчеркивает:
В частности.....
беззамочные:
- TryGetValue
- GetEnumerator
- Индексатор геттер
- ContainsKey
Вынимает каждый замок (lockfull?):
- подсчитывать
- Пустой
- Ключи
- Ценности
- Скопировать в
- ToArray