Является ли linq-запрос для ConcurrentDictionary Values потокобезопасным?
скажем, у меня есть следующий код:
ConcurrentDictionary<long, long> myDict= new ConcurrentDictionary<long, long>();
Обычно каждый доступ по ключу является потокобезопасным, но также является следующим linq-запросом threadsafe?
Я ничего не нашел в документах:
http://msdn.microsoft.com/en-us/library/dd287226.aspx
if myDict.Values.Any(x => !x.HasPaid))
{
return false
}
Ответы
Ответ 1
Коррекция... Я не уверен, когда вы обращаетесь к свойству "Значения". Это потокобезопасность при использовании LINQ для самого объекта.
LINQ будет использовать метод GetEnumerator для итерации элементов.
Прямо от MSDN
Перечислитель, возвращаемый из словаря, безопасен для одновременного использования с чтением и записью в словарь, однако он не представляет моментальный снимок словаря во времени. Содержимое, отображаемое через счетчик, может содержать изменения, внесенные в словарь после того, как GetEnumerator был вызван
if myDict.Any(x => !x.Value.HasPaid))
{
return false
}
Ответ 2
Как уже упоминалось, ConcurrentDictionary.GetEnumerator() не представляет моментальный снимок словаря в момент времени. Однако ConcurrentDictionary.Values создает моментальный снимок момента времени.
Следовательно, следующие не эквивалентны:
myDict.Any(x => !x.Value.HasPaid)
myDict.Values.Any(x => !x.HasPaid)
Ответ 3
Документация ConcurrentDictionary гласит:
Все общедоступные и защищенные члены ConcurrentDictionary являются потокобезопасными и могут использоваться одновременно из нескольких потоков.
Так как свойство .Values является реализацией, продиктованной интерфейсом IColletion, оно является общедоступным и, следовательно, безопасным потоком.
Ответ 4
Все ответы пока прекрасны и полезны, но я думаю, что ссылка, которую DuneCat указала в одном из комментариев, имеет особое значение:
http://geekswithblogs.net/simonc/archive/2012/02/22/inside-the-concurrent-collections-concurrentdictionary.aspx
В частности.....
беззамочные:
- TryGetValue
- GetEnumerator
- Узел индексатора
- ContainsKey
Вынимает каждый замок (lockfull?):
- Count
- IsEmpty
- Клавиши
- Значения
- CopyTo
- ToArray