.NET – блокировка словаря против ConcurrentDictionary

Я не мог найти достаточно информации о типах ConcurrentDictionary , поэтому я подумал, что я бы спросил об этом здесь.

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

Недавно я узнал, что в .NET 4.0 существует набор поточно-безопасных коллекций, и это кажется очень приятным. Мне было интересно, каков будет вариант «более эффективный и простой в управлении», так как у меня есть возможность между обычным Dictionary с синхронизированным доступом или иметь ConcurrentDictionary который уже является streamобезопасным.

Ссылки на ConcurrentDictionary .NET 4.0

Потокобезопасную коллекцию по сравнению с не-streamобезопасной коллекцией можно посмотреть по-другому.

Рассмотрите магазин без клерка, кроме как при оформлении заказа. У вас много проблем, если люди не действуют ответственно. Например, предположим, что клиент берет банку из пирамиды, пока клерк в настоящее время строит пирамиду, весь ад сломается. Или, что, если два клиента достигнут одного и того же предмета одновременно, кто победит? Будет ли бой? Это нетекающая коллекция. Существует множество способов избежать проблем, но все они требуют какой-то блокировки или, скорее, явного доступа в той или иной форме.

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

Теперь рассмотрим это. В магазине с одним клерком, что, если вы доберетесь до передней части линии и попросите клерка «У вас есть туалетная бумага», и он говорит «Да», а затем вы идете «Хорошо, я», я вернусь к вам, когда я знаю, сколько мне нужно », то к тому времени, когда вы вернетесь на фронт линии, магазин, конечно же, может быть распродан. Этот сценарий не препятствует сборке streamовых сетей.

Коллекция streamобезопасности гарантирует, что ее внутренние структуры данных действительны во все времена, даже если они доступны из нескольких streamов.

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

Однако assembly streamобезопасности гарантирует, что последовательные операции над streamом работают с одним и тем же «снимком» его внутренней структуры данных, а это значит, что если у вас есть такой код:

 if (tree.Count > 0) Debug.WriteLine(tree.First().ToString()); 

вы можете получить исключение NullReferenceException, потому что inbetween tree.Count и tree.First() , другой stream очистил оставшиеся узлы в дереве, что означает, что First() вернет null .

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

Вы все еще должны быть очень осторожны при использовании поточно-безопасных коллекций, потому что streamобезопасность не означает, что вы можете игнорировать все проблемы с streamами. Когда коллекция рекламирует себя как streamобезопасную, обычно это означает, что она остается в согласованном состоянии, даже когда несколько streamов читают и записывают одновременно. Но это не означает, что один stream будет видеть «логическую» последовательность результатов, если он вызывает несколько методов.

Например, если вы сначала проверите, существует ли ключ, а затем получите значение, соответствующее ключу, этот ключ больше не может существовать даже с версией ConcurrentDictionary (поскольку другой stream мог удалить ключ). Вам все равно нужно использовать блокировку в этом случае (или лучше: объединить два вызова с помощью TryGetValue ).

Так что используйте их, но не думайте, что он дает вам бесплатный проход, чтобы игнорировать все проблемы параллелизма. Вы все еще должны быть осторожны.

Внутри ConcurrentDictionary используется отдельный замок для каждого hash-ведра. До тех пор, пока вы используете только Add / TryGetValue и подобные методы, которые работают с одиночными записями, словарь будет работать как почти блокируемая структура данных с соответствующей слабой производительностью. OTOH перечисляющие методы (включая свойство Count) блокируют все ковши сразу и, следовательно, хуже, чем синхронизированный Словарь, по производительности.

Я бы сказал, просто используйте ConcurrentDictionary.

Вы видели Reactive Extensions для .Net 3.5sp1. По словам Джона Скита, они предоставили пакет параллельных расширений и параллельных структур данных для .Net3.5 sp1.

Существует набор образцов для .Net 4 Beta 2, в котором довольно подробно описаны способы использования параллельных расширений.

Я только что провел последнюю неделю, проверив ConcurrentDictionary, используя 32 streamа для выполнения операций ввода-вывода. Кажется, он работает как рекламируемый, что указывает на то, что в него было внесено огромное количество тестов.

Изменить : .NET 4 ConcurrentDictionary и шаблоны.

Microsoft выпустила pdf-файл под названием «Шаблоны программирования Paralell». Его поистине стоит скачать, поскольку он описывает в действительно хороших деталях правильные шаблоны для использования .Net 4 параллельных расширений и анти-шаблонов, которых следует избегать. Вот.

Я думаю, что метод ConcurrentDictionary.GetOrAdd – это именно то, что нужно большинству многопоточных сценариев.

В основном вы хотите пойти с новым ConcurrentDictionary. Прямо из коробки вы должны написать меньше кода, чтобы создавать streamобезопасные программы.

Мы использовали ConcurrentDictionary для кэшированной коллекции, которая повторно заполняется каждые 1 час, а затем считывается несколькими клиентскими streamами, аналогично решению для этого примера. вопрос.

Мы обнаружили, что изменение его в ReadOnlyDictionary улучшило общую производительность.

Существует хороший курс о параллельных коллекциях в c #: параллельные коллекции Pluralsight

  • Как объединить hashи в Perl?
  • Как реализован словарь c # /. Net 3.5?
  • Есть ли общеansible словарь для чтения, ansible в .NET?
  • Преобразование списка кортежей в словарь
  • Как реализовать ConcurrentHashSet в .Net
  • Итерация через словарь в Swift
  • Словарь, возвращающий значение по умолчанию, если ключ не существует
  • Определение, если словарь Swift содержит ключ и получает какие-либо его значения
  • Порядок элементов в словаре
  • c # словарь один ключ многие значения
  • Как вы сортируете словарь по значению?
  • Interesting Posts

    Замена заметок Outlook или альтернативы?

    Как синхронизировать каталоги за пределами каталога Google Диска

    Как установить Firefox 4 только для хранения истории в течение заданного периода времени, то есть в один прекрасный день?

    Java-создание байтового массива, размер которого представлен длинным

    WPF: Как сделать автоматическое изменение размера canvasа?

    Как сохранить пропорции виджетов в Qt?

    Почему использование обновления на lm внутри сгруппированных data.table потеряет данные модели?

    Найдите, находится ли точка внутри выпуклой оболочки для набора точек без вычисления самого корпуса

    Как разделять и присоединяться без перекодирования видеофайлов AVC / MPEG-TS в Windows с помощью ffmpeg?

    Настройка переменных динамической области в AngularJs – область.

    Сортировка данных Firebase Desc в Android

    Как конвертировать отдельные изображения в видео с переходом на смешение?

    с помощью facebook sdk в студии Android

    Почему размер файла CBS.log составляет 20 ГБ

    получить все ключи, установленные в memcached

    Давайте будем гением компьютера.