Структуры данных для параллельного программирования
Платформа .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. |
Дополнительные сведения см. в разделе:
Практическое руководство. SpinLock и низкоуровневая синхронизация
Практическое руководство. Синхронизация параллельных операций с барьером.
Классы отложенной инициализации
При использовании отложенной инициализации память выделяется объекту только в тот момент, когда она нужна. Отложенная инициализация позволяет повысить производительность, равномерно распределяя процессы выделения объектов на вест период существования программы. Чтобы включить отложенную инициализацию для любого пользовательского типа, упакуйте в него тип 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.