.NET - блокировка словаря и ConcurrentDictionary



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



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



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



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

654   8  

8 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Edit: .NET 4 ConcurrentDictionary и шаблоны.

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

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

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

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

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

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

вы можете найти всю интересную информацию там.

Comments

    Ничего не найдено.