- •Процессы, нити и волокна
- •CrProces.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •Объекты синхронизации
- •Защита процесса от нереентрабельного кода
- •Описание функций управления процессами, нитями и волокнами
- •CreateEvent
- •CrEvent.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateMutex
- •CrMutex.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateSemaphore
- •CrSem.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •CreateThread
- •EnterCriticalSection
- •EntCrSec.C
- •Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,
- •ExitThread
- •InitializeCriticalSection
- •DeleteCriticalSection
- •LeaveCriticalSection
- •OpenSemaphore
- •TryEnterCriticalSection
- •WaitForMultipleObjects
Объекты синхронизации
В связи с тем что Windows 9.x и Windows NT/2000 присуща вытесняющая многозадачность, возможность доступа двух нитей к одной и той же области памяти внутри процесса оказывается проблематичной. Некоторые нити не имеют доступа к памяти либо выполняют операции, которые оказывают влияние на другие нити внутри процесса. Однако если нити не разделяют общие ресурсы процесса или системные ресурсы, либо они должны выполняться согласованно, то в этом случае требуется определенная их синхронизация. Для совместной работы нитей без разрушения памяти в интерфейсе Win32 API предоставляются объекты синхронизации (synchronization objects). Объекты синхронизации обеспечивают доступ к системным ресурсам, которые могут находиться под управлением нитей одних и тех же либо других процессов.
Тремя основными типами объектов синхронизации являются мьютексы, семафоры и события. Эти объекты синхронизации отличаются друг от друга условием установки сигнального состояния. Наиболее распространенные объекты синхронизации перечислены в табл. 1.
Таблица 1. Основные объекты синхронизации процессов
Объект |
Назначение |
Мьютекс |
Разрешает взаимно исключающий доступ |
Семафор |
Разрешает доступ к известному числу нитей |
Событие |
Разрешает доступ к любому числу ожидающих нитей |
Объект синхронизации обладает двумя состояниями: сигнальным и несигнальным. Когда объект синхронизации находится в состоянии занятости, или несигнальном состояния, выполнение ожидающей нити не может быть продолжено. А когда объект синхронизации оказывается в сигнальном состоянии, ожидающая нить может продолжить свое выполнение.
Функции ожидания (wait functions) представляют собой набор вызовов API, которые приостанавливают выполнение нитей до тех пор, пока не станет истинным заданный ряд условий. Функции ожидания проверяют сигнальное состояние объектов синхронизации. Если указанный объект оказывается в сигнальном состоянии, функция ожидания завершается, а выполнение нити продолжается. В противном случае функция ожидания будет поддерживать нить в хорошо оптимизированном цикле, опрашивая состояние объекта синхронизации до тех пор, пока оно не станет сигнальным либо не истечет время ожидания.
Название мъютекса (mutex object) происходит от понятия "взаимное исключение" (mutual exclusion). Мьютекс может одновременно принадлежать только одной нити. Следовательно, если мьютекс принадлежит одной нити, а другая нить запрашивает права владения им, то запрашивающая нить может получить эти права на мьютекс лишь в том случае, когда владеющая им нить уступит свои права. Известный мьютекс Winl6Lock или Winl6Mutex используется в Windows 9.x для защиты нереентрабельного 16-разрядного кода в интерфейсе GDI и USER от опасности одновременного выполнения. В примере, приведенном в описании функции CreateMutex далее в главе, продемонстрировано применение мьютексов.
Семафор (semaphore object) начинает действовать с назначенного для него начального отсчета. Всякий раз когда нить получает права владения этим объектом (через функцию ожидания), счетчик в семафоре уменьшается на единицу. И всякий раз когда нить уступает свои права владения этим объектом, счетчик в семафоре увеличивается на единицу. Как только счетчик в семафоре достигает нуля, семафор блокируется в несигнальном состоянии и ни одна из нитей не может получить к нему доступ.
Одним из удачных примером применения семафора служит управление распределением конечных ресурсов. Управление запросом каждого ресурса выполняет семафор, действие которого автоматически прекращается по достижении запрограммированного предела. Всякий раз когда запрашивающей нити уже не требуется ресурс, семафор освобождается. Значение счетчика в семафоре всегда сравнимо с количеством доступных ресурсов. Семафоры используются в примере, приведенном в описании функции CreateSemaphore далее в главе.
События (event objects) позволяют синхронизировать доступ к ресурсу со стороны любого числа нитей. При этом доступ к ресурсу предоставляется программным путем. Существует два вида событий: события, сбрасываемые вручную, и события, сбрасываемые автоматически.
Сбрасываемое вручную событие (manual-reset event object) устанавливается в сигнальное состояние программным путем через вызов функции SetEvent. Событие переходит в несигнальное состояние после обращения к функции ResetEvent. Функция PulseEvent устанавливает и сбрасывает события по очереди. Сбрасываемые вручную события разрешают всем нитям, ожидающим наступления такого события, продолжить свое выполнение. Сбрасываемые вручную события используются в примере, приведенном в описании функции CreateEvent далее в главе.
Автоматически сбрасываемое событие (auto-reset event object) сбрасывается самостоятельно после освобождения одной ожидающей нити. Все остальные нити продолжают ожидать до тех пор, пока данное событие опять не перейдет в несигнальное состояние. Автоматически сбрасываемые события разрешают управляемый последовательный доступ к синхронизированному коду нитям разных процессов подобно тому, как объекты критических участков кода разрешают нитям одного и того же процесса последовательный доступ к коду. Автоматически сбрасываемые события используются в примере, приведенном в описании функции OpenEvent далее в этой главе.
Кроме того, в приложении в качестве объектов синхронизации можно использовать объекты, перечисленные в табл. 2. Они не переходят в несигнальное состояние до тех пор, пока не возникнет заданное условие.
Таблица 2. Другие объекты синхронизации
Объект |
Сигнальное условие |
Уведомление об изменении |
Переходит в сигнальное состояние, когда происходит заданное изменение в структуре файловой системы |
Ввод с консоли |
Переходит в сигнальное состояние по готовности непрочитанного ввода с консоли |
Процесс |
Переходит в сигнальное состояние при завершении процесса |
Нить |
Переходит в сигнальное состояние при завершении нити |