Объекты синхронизации в Windows.
В операционной системе Windows поддерживаются четыре типа объекта синхронизации.
- Первый тип представляет собой классический семафор и может быть использован для управления доступом к определенным ресурсам ограниченного количества потоков. Разделяемый ресурс в этом случае может быть использован одним, и только одним потоком, либо некоторым числом потоков из множества претендующих на этот ресурс. Семафоры реализуются как простые счетчики, значения которых увеличиваются, когда поток освобождает семафор, и уменьшаются, когда поток занимает семафор.
- Второй тип объектов синхронизации называется исключающим семафором (mutex). Исключающие семафоры применяются для разделения ресурсов таким образом, что в любой момент времени их может использовать один и только один поток. Очевидно, что исключающий семафор представляет собой специальный тип обычного семафора.
- Третий тип объектов синхронизации - это событие (event). События могут служить для блокировки доступа к ресурсу до тех пор, пока другой поток не сигнализирует об его освобождении.
- Четвертый тип объектов синхронизации представляет собой критическую секцию (critical section). При вхождении потока в критическую секцию никакой другой поток не может начать ее выполнение до того, как работающий с ней поток не выйдет из нее.
Следует отметить, что синхронизация потоков с помощью критических секций может осуществляться только в рамках одного процесса, так как невозможно передать адрес критической секции из одного процесса в другой, так как критическая секция располагается в области глобальных переменных запущенного процесса.
Семафор создается с помощью функции CreateSemaphore. Количество задач, одновременно имеющих доступ к некоторому ресурсу, определяется одним из параметров функции. Если значение этой функции равно 1, то семафор работает как исключающий. При успешном создании семафора возвращается его дескриптор, в противном случае - null. Функция WaitForSingleObject обеспечивает режим ожидания семафора. Один из параметров указывает время его ожидания в миллисекундах. Если значение этого параметра равно INFINITE, то время ожидания неопределено. При успешном завершении функции значение счетчика, связанного с семафором, уменьшается не единицу. Функция ReleaseSemaphore() освобождает семафор, позволяя использовать его другому потоку.
Исключающий семафор mutex создается с помощью функции CreateMutex(), которая возвращает идентификатор созданного объекта или null в случае ошибки. В случае необходимости объект освобождается с помощью универсальной функции CloseHandle(). Зная имя объекта mutex, его можно открыть с помощью функции OpenMutex(). С помощью этой функции несколько потоков могут открыть один и тот же объект, а затем одновременно выполнить его ожидание. После того, как имя объекта стало известно потоку, он может им завладеть, используя функции WaitForSingleObject или WaitForMultipleObjects. Освобождение объекта mutex осуществляется с помощью функции ReleaseMutex().
Событие создается с помощью функции CreateEvent. Она возвращает дескриптор созданного события или null в случае неуспешного завершения. После создании события поток просто ожидает его наступления используя функцию WaitForSingleObject, задавая в качестве первого параметра для нее дескриптор этого события. Тем самым выполнение потока приостанавливается до наступления соответствующего события. После вызова функции SetEvent процесс, ожидающий данного события с помощью функции WaitForSingleObject, продолжит свое выполнение. Событие может быть сброшено с помощью функции ResetEvent.
Критическая секция создается как структура типа CRITICAL_SECTION. Перед использованием она должна быть проинициализирована с помощью функции InitializeCriticalSection(). В случае необходимости критическая секция может быть удалена с помощью функции DeleteCriticalSection(). При этом освобождаются все ресурсы, созданные операционной системой для критической секции. Для входа в критическую секцию используется функция EnterCriticalSection(), для выхода из критической секции используется функция LeaveCriticalSection().