Поделиться через


Потокобезопасные коллекции

Пространство System.Collections.Concurrent имен включает несколько классов коллекций, которые являются потокобезопасными и масштабируемыми. Несколько потоков могут безопасно и эффективно добавлять или удалять элементы из этих коллекций, не требуя дополнительной синхронизации в пользовательском коде. При написании нового кода используйте параллельные классы коллекции для одновременной записи нескольких потоков в коллекцию. Если вы читаете только из общей коллекции, используйте классы в System.Collections.Generic пространстве имен.

System.Collections и System.Collections.Generic

Классы коллекции в System.Collections пространстве имен включают ArrayList и Hashtable. Эти классы обеспечивают некоторую безопасность потоков с помощью свойства Synchronized, которое возвращает потокобезопасную оболочку для коллекции. Оболочка работает путем блокировки всей коллекции при каждой операции добавления или удаления. Таким образом, каждый поток, пытающийся получить доступ к коллекции, должен ждать своей очереди, чтобы получить доступ к единственному замку. Этот процесс не масштабируется и может привести к значительному снижению производительности для больших коллекций. Кроме того, дизайн не защищен от условий гонки. Дополнительные сведения см. в разделе "Синхронизация в универсальных коллекциях".

Классы коллекции в System.Collections.Generic пространстве имен включают List<T> и Dictionary<TKey,TValue>. Эти классы обеспечивают улучшенную безопасность типов и производительность по сравнению с System.Collections классами. System.Collections.Generic Однако классы не обеспечивают синхронизацию потоков. Пользовательский код должен обеспечить всю синхронизацию при добавлении или удалении элементов на нескольких потоках одновременно.

Мы рекомендуем использовать параллельные классы коллекций System.Collections.Concurrent в пространстве имен, так как они обеспечивают безопасность типов, а также более эффективную и полную безопасность потоков.

Механизмы тонкой блокировки и безблокировочные механизмы

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

Классы ConcurrentQueue<T> и ConcurrentStack<T> вообще не используют блокировки. Вместо этого они полагаются на Interlocked операции, чтобы обеспечить безопасность потока.

Замечание

Так как параллельные классы коллекций поддерживают ICollection, они предоставляют реализации для IsSynchronized свойств и SyncRoot свойств, даже если эти свойства не имеют значения. IsSynchronized всегда возвращается false и SyncRoot всегда null (Nothing в Visual Basic).

Ниже приведена таблица, в которой перечислены типы коллекций в пространстве имен System.Collections.Concurrent.

Тип Описание
BlockingCollection<T> Предоставляет ограничивающие и блокирующие функции для любого типа, реализующего IProducerConsumerCollection<T>. Дополнительные сведения см. в разделе "Обзор BlockingCollection".
ConcurrentDictionary<TKey,TValue> Потокобезопасная реализация словаря пар «ключ-значение».
ConcurrentQueue<T> Потокобезопасная реализация очереди FIFO (первым пришёл — первым ушёл).
ConcurrentStack<T> Потокобезопасная реализация стека LIFO (последний вошёл, первый вышел).
ConcurrentBag<T> Потокобезопасная реализация неупорядоченной коллекции элементов.
IProducerConsumerCollection<T> Интерфейс, который должен реализовывать тип для использования в объекте BlockingCollection.
Название Описание
Обзор BlockingCollection Описывает функциональные возможности, предоставляемые типом BlockingCollection<T> .
Как: Добавить и удалить элементы из конкурентного словаря Описание добавления и удаления элементов из ConcurrentDictionary<TKey,TValue>
Практическое руководство: Добавление и изъятие элементов по отдельности из BlockingCollection Описывается процесс добавления и извлечения элементов из блокирующей коллекции без использования перечислителя только для чтения.
Практическое руководство. Добавление ограничивающих и блокирующих функций в коллекцию Описывает, как использовать любой класс коллекции в качестве базового механизма хранения для IProducerConsumerCollection<T> коллекции.
Как использовать ForEach для удаления элементов в BlockingCollection Описание использования foreach (For Each в Visual Basic) для удаления всех элементов в коллекции блокировок.
Практическое руководство. Использование массивов блокирующих коллекций в конвейере Определяет, как использовать несколько блокирующих коллекций одновременно для реализации конвейера.
Как создать пул объектов с помощью ConcurrentBag Показывает, как использовать одновременный пакет для повышения производительности в сценариях, где можно повторно использовать объекты вместо постоянного создания новых.

Справка