Подтвердить что ты не робот

Является ли 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
}
4b9b3361

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