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


Синхронизация выполнения нескольких потоков

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

Существует несколько объектов, дескрипторы которых можно использовать для синхронизации множества потоков. К этим объектам относятся:

  • Входные буферы консоли
  • События
  • Мьютексы
  • Процессы
  • Семафоры
  • Потоки
  • Таймеры

Состояние каждого из этих объектов либо сигнализируется, либо не сигналируется. При указании дескриптора для любого из этих объектов в вызове одной из функций ожидания выполнение вызывающего потока блокируется до тех пор, пока состояние указанного объекта не установится в сигнальное состояние.

Некоторые из этих объектов полезны при блокировке потока до тех пор, пока не произойдет какое-то событие. Например, дескриптор входного буфера консоли подаёт сигнал при наличии непрочитанных данных, таких как нажатие клавиши или щелчок кнопкой мыши. Обработчики процессов и потоков уведомляются при завершении процесса или потока. Это позволяет процессу, например, создавать дочерний процесс, а затем блокировать собственное выполнение до завершения нового процесса.

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

Для потоков одного процесса объекты критических секций предоставляют более эффективные средства синхронизации по сравнению с мьютексами. Критическая секция используется как мьютекс, чтобы позволить одному потоку одновременно использовать защищенный ресурс. Поток может использовать функцию EnterCriticalSection для запроса владения критически важным разделом. Если он уже принадлежит другому потоку, запрашивающий поток блокируется. Поток может использовать функцию TryEnterCriticalSection для запроса владения критическим разделом, не блокируя его в случае неудачи. После получения права владения поток может использовать защищенный ресурс. Выполнение других потоков процесса не затрагивается, если они не пытаются войти в тот же критический раздел.

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

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