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


Структуры данных для параллельного программирования

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

Классы параллельных коллекций

Классы коллекций в пространства имен System.Collections.Concurrent поддерживают потокобезопасные операции добавления и удаления, которые избегают блокировок везде, где это возможно, и применяют только детально настроенные блокировки. Класс параллельных коллекций не требует использовать блокировки в пользовательском коде для доступа к элементам. Классы параллельных коллекций могут значительно повысить производительность по сравнению с типами System.Collections.ArrayList и System.Collections.Generic.List<T> (где блокировка реализуется пользователем) в сценариях одновременного добавления и удаления элементов коллекции из нескольких потоков.

В приведенной ниже таблице перечислены классы параллельных коллекций.

Тип Описание
System.Collections.Concurrent.BlockingCollection<T> Предоставляет возможности блокировки и ограничения для потокобезопасных коллекций, реализующих System.Collections.Concurrent.IProducerConsumerCollection<T>. Потоки-производителя блокируются, если нет доступных слотов или коллекция заполнена. Потоки-потребители блокируются, если коллекция пуста. Этот тип также поддерживает неблокирующий доступ для потребителей и производителей. BlockingCollection<T> можно использовать в качестве базового класса или резервного хранилища с поддержкой блокировок и ограничений для любого класса коллекции с поддержкой IEnumerable<T>.
System.Collections.Concurrent.ConcurrentBag<T> Потокобезопасная реализация контейнера, которая предоставляет масштабируемые операции добавления и получения.
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> Тип параллельного и масштабируемого словаря.
System.Collections.Concurrent.ConcurrentQueue<T> Параллельная и масштабируемая очередь FIFO.
System.Collections.Concurrent.ConcurrentStack<T> Параллельный и масштабируемый стек LIFO.

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

Примитивы синхронизации

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

В приведенной ниже таблице перечислены типы синхронизации.

Тип Описание
System.Threading.Barrier Позволяет нескольким потокам работать над выполнением алгоритма параллельно, поддерживая точку регистрации, в которой каждая задача отмечает свою доступность и ожидает новых задач. Дополнительные сведения см. в разделе Барьер.
System.Threading.CountdownEvent Упрощает сценарии ветвления и соединения, предоставляя удобный механизм взаимодействия. Более подробную информацию можно найти в описании события CountdownEvent.
System.Threading.ManualResetEventSlim Примитив синхронизации, аналогичный System.Threading.ManualResetEvent. ManualResetEventSlim менее требователен к ресурсам, но пригоден только для обмена данными внутри процесса.
System.Threading.SemaphoreSlim Примитив синхронизации, который ограничивает количество потоков, одновременно обращающихся к ресурсу или пулу ресурсов. Дополнительные сведения см. в описании классов Semaphore и SemaphoreSlim.
System.Threading.SpinLock Примитив взаимоисключающей блокировки, при использовании которого поток, который пытается получить блокировку, применяет цикл ожидания в течение заданного времени, прежде чем получить свою часть времени. В сценариях, где прогнозируется короткий период ожидания блокировки, SpinLock обеспечит более высокую производительность по сравнению с другими формами блокировки. Дополнительные сведения см. в описании SpinLock.
System.Threading.SpinWait Небольшой и нетребовательный к ресурсам тип, который реализует небольшую паузу, и только по истечении заданного времени переходит в состояние ожидания. Дополнительные сведения см. в описании SpinWait.

Дополнительные сведения см. в разделе:

Классы отложенной инициализации

При использовании отложенной инициализации память выделяется объекту только в тот момент, когда она нужна. Отложенная инициализация позволяет повысить производительность, равномерно распределяя процессы выделения объектов на вест период существования программы. Чтобы включить отложенную инициализацию для любого пользовательского типа, упакуйте в него тип Lazy<T>.

В следующей таблице перечислены типы отложенной инициализации.

Тип Описание
System.Lazy<T> Легкая и потокобезопасная реализация отложенной инициализации.
System.Threading.ThreadLocal<T> Предоставляет отложенно инициализированное значение для каждого потока, при этом каждый поток вызывает функцию отложенной инициализации.
System.Threading.LazyInitializer Предоставляет статические методы, которые избавляют от необходимости выделять экземпляр отложенной инициализации. Вместо этого он использует ссылки, гарантирующие инициализацию целевых объектов при первом обращении к ним.

Дополнительные сведения см. в статье Отложенная инициализация.

Агрегатные исключения

Тип System.AggregateException позволяет захватить несколько исключений, создаваемых одновременно в нескольких отдельных потоках, и передать их в присоединяемый поток в виде одного исключения. Типы System.Threading.Tasks.Task и System.Threading.Tasks.Parallel, а также PLINQ, широко используют для этой цели AggregateException. Дополнительные сведения см. в статьях Обработка исключений и Практическое руководство. Обработка исключений в запросах PLINQ.

См. также