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


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

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

Синхронизация потоков в пространстве имен Collections на платформах .NET Framework версий 1.0 и 2.0

Доступные на платформе .NET Framework 1.0 коллекции находятся в пространстве имен System.Collections. Эти коллекции, которые содержат часто используемые класс ArrayList и класс Hashtable, предоставляют некоторую потокобезопасность посредством свойства Synchronized, которое возвращает потокобезопасную программу-оболочку вокруг коллекции. Работа программы оболочки заключается в блокировке всей коллекции при каждой операции добавления или удаления. Поэтому каждый поток, который пытается получить доступ к коллекции, должен ждать своей очереди для получения блокировки. Такой подход не является масштабируемым и может привести к значительному снижению производительности для больших коллекций. Также такой подход не защищен полностью от состояния гонки. Дополнительные сведения см. в разделе Синхронизация в универсальных коллекциях на сайте MSDN.

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

Рекомендуются классы параллельных коллекций на платформе .NET Framework 4 так как они предоставляют не только безопасность типа классов коллекций платформы .NET Framework 2.0, но и большую эффективность, более полную потокобезопасность по сравнению с коллекциями .NET Framework 1.0.

Механизм блокировки мелких фрагментов данных и механизм, свободный от блокировки

Отдельные из типов параллельных коллекций используют механизмы упрощенной синхронизации, например, SpinLock, SpinWait, SemaphoreSlim, CountdownEvent, которые появились на платформе .NET Framework 4. Эти типы синхронизации обычно используют цикличную работу для коротких промежутков перед помещением потока в фактическое состояние ожидания. При условии, что время ожидания предполагается очень коротким, цикличность требует значительно меньших затрат компьютерных ресурсов, чем ожидание, которое включает в себя переход в режим ядра, который требует больших затрат компьютерных ресурсов. Для классов коллекций, которые используют цикличность, эта эффективность означает, что множество потоков могут добавлять и удалять большое количество элементов. Дополнительные сведения о цикличности и блокировке см. в разделах 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 и их удаление из этой коллекции

Приводится описание порядка добавления и удаления элементов из класса ConcurrentDictionary<TKey, TValue>

Практическое руководство. Добавление и удаление отдельных элементов коллекции BlockingCollection

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

Практическое руководство. Добавление функций границы и блокировки в класс коллекции

Приводится описание порядка использования всех классов коллекций в качестве базового механизма хранения для коллекции IProducerConsumerCollection<T>.

Практическое руководство. Использование оператора ForEach для удаления элементов в коллекции BlockingCollection

Приводится описание порядка использования конструкции foreach, (For Each в Visual Basic) для удаления всех элементов в заблокированной коллекции.

Практическое руководство. Использование массивов для блокировки коллекций в конвейере

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

Практическое руководство. Создание пула объектов с помощью класса ConcurrentBag

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

Ссылка

System.Collections.Concurrent