Структуры данных синхронизации

Среда выполнения с параллелизмом предоставляет несколько структур данных, позволяющих синхронизировать доступ к совместно используемым данным из нескольких потоков. Эти структуры данных удобны для редко изменяемых совместно используемых данных. Объект синхронизации, например критическая секция, заставляет другие потоки ожидать, пока совместно используемый ресурс не станет доступен. Поэтому если использовать такой объект для синхронизации доступа к часто используемым данным, приложение может утратить масштабируемость. Библиотека Библиотека параллельных шаблонов предоставляет класс Concurrency::combinable, позволяющий нескольким потокам или задачам совместно использовать ресурс без необходимости синхронизации. Дополнительные сведения о классе combinable см. в разделе Параллельные контейнеры и объекты.

Подразделы

В этом разделе подробно рассматриваются следующие типы асинхронных блоков сообщений.

  • critical_section

  • reader_writer_lock

  • scoped_lock и scoped_lock_read

  • event

critical_section

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

Класс critical_section является нереентерабельным. При вызове из потока, уже владеющего блокировкой, метод Concurrency::critical_section::lock вызывает исключение типа Concurrency::improper_lock.

Методы и свойства

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

Метод

Описание

lock

Получает критическую секцию. Вызывающий контекст блокируется, пока не получит блокировку.

try_lock

Пытается получить критическую секцию, но не выполняет блокировку.

unlock

Освобождает критическую секцию.

[в начало]

reader_writer_lock

Класс Concurrency::reader_writer_lock предоставляет потокобезопасные операции чтения и записи совместно используемых данных. Используйте блокировки чтения/записи, если нескольким потокам требуется параллельный доступ на чтение из совместно используемого ресурса, а запись в этот совместно используемый ресурс производится редко. В любой момент времени этот класс предоставляет доступ для записи в этот объект только одному потоку.

Класс reader_writer_lock может обеспечивать большую производительность, чем класс critical_section, так как объект critical_section получает эксклюзивный доступ к совместно используемому ресурсу, исключающий параллельный доступ для чтения.

Как и класс critical_section, класс reader_writer_lock представляет собой кооперативный взаимоисключающий объект, который выдается другим задачам, а не завладевает ими.

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

Как и класс critical_section, класс reader_writer_lock является нереентерабельным. При вызове из потока, уже владеющего блокировкой, методы Concurrency::reader_writer_lock::lock и Concurrency::reader_writer_lock::lock_read вызывают исключение типа improper_lock.

Примечание

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

Методы и свойства

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

Метод

Описание

lock

Получает доступ к блокировке для чтения/записи.

try_lock

Пытается получить доступ к блокировке для чтения/записи, но не выполняет блокировку.

lock_read

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

try_lock_read

Пытается получить доступ только для чтения к блокировке, но не выполняет блокировку.

unlock

Снимает блокировку.

[в начало]

scoped_lock и scoped_lock_read

Классы critical_section и reader_writer_lock предоставляют вложенные вспомогательные классы, упрощающие способ работы с взаимоисключающими объектами. Эти вспомогательные классы называются блокировками с областью.

Класс critical_section содержит класс Concurrency::critical_section::scoped_lock. Конструктор получает доступ к предоставленному объекту critical_section; деструктор освобождает доступ к этому объекту. Класс reader_writer_lock содержит класс Concurrency::reader_writer_lock::scoped_lock, похожий на класс critical_section::scoped_lock, но управляющий доступом для записи к предоставленному объекту reader_writer_lock. Класс reader_writer_lock также содержит класс Concurrency::reader_writer_lock::scoped_lock_read. Этот класс управляет доступом на чтение к предоставленному объекту reader_writer_lock.

Блокировки с областью имеют несколько преимуществ при работе с объектами critical_section и reader_writer_lock вручную. Обычно блокировка с областью размещается в стеке. Блокировка с областью освобождает доступ к своему взаимоисключающему объекту автоматически при ее уничтожении; поэтому не требуется вручную разблокировать основной объект. Это удобно, если функция содержит несколько операторов return. Блокировки с областью также помогают создавать код, безопасный в отношении исключений. Когда оператор throw вызывает раскручивание стека, вызываются деструкторы всех активных блокировок с областью, и поэтому взаимоисключающий объект всегда правильно освобождается.

Примечание

При использовании классов critical_section::scoped_lock, reader_writer_lock::scoped_lock и reader_writer_lock::scoped_lock_read не освобождайте доступ к основному взаимоисключающему объекту вручную.В результате среда выполнения может перейти в недопустимое состояние.

event

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

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

Методы и свойства

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

Метод

Описание

wait

Ожидает перехода события в сигнальное состояние.

set

Устанавливает событие в сигнальное состояние.

reset

Устанавливает событие в несигнальное состояние.

wait_for_multiple

Ожидает, пока несколько событий перейдут в сигнальное состояние.

Пример

Пример, показывающий использование класса event, см. в разделе Сравнение структур данных синхронизации с интерфейсом Windows API.

[в начало]

Связанные разделы