Синхронизация параллельных потоков
Объект взаимоисключения mutex может быть использован для организации взаимоисключения потоков как одного, так и разных процессов. Однако, для организации взаимоисключения потоков в рамках одного процесса в WIN32 предусмотрен более простой в использовании механизм критических секций. Критическая секция объявляется как структура типа CRITICAL_SECTIONв области глобальных переменных, доступной всем потокам процесса. Перед использованием критической секции ее необходимо проинициализировать при помощи функции InitializeCriticalSection. Для входа в критическую секцию вызывается функция EnterCriticalSection, а для выхода – функция LeaveCriticalSection. Если критическая секция больше не нужна, ее следует удалить при помощи функции DeleteCriticalSection. Ниже приведен фрагмент кода, иллюстрирующий использование критических секций:
CRITICAL_SECTION critsect;
InitializeCriticalSection(&critsect);
. . .
EnterCriticalSection(&critsect);
Критический участок
LeaveCriticalSection(&critsect);
. . .
DeleteCriticalSection(&critsect);
76
Объект ядра семафор (semaphore) используется для организации последовательногодоступа потоков к общему ресурсу. По своему назначению семафор похож на объект взаимоисключения mutex, но в отличие от последнего позволяет обеспечить параллельное выполнение критических участков (доступ к ресурсу) для ограниченного числа потоков. Поток, пытающийся получить доступ к ресурсу сверх установленного лимита будет блокирован на семафоре до тех пор, пока какой-либо поток не завершит выполнение критического участка, связанного с семафором (освободит ресурс). Для создания семафора используется функция CreateSemaphore, а для его открытия – функция OpenSemaphore. При создании семафора производится инициализация счетчика семафора значением, переданным через один из параметров функции CreateSemaphore, и объект ядра семафор переводится в состояние signaled. Над любым семафором определены две операции: операция P и операция V. Перед входом в критический участок, контролируемый семафором, поток должен выполнить операцию P, а перед выходом из критического участка – операцию V. Операция P состоит в проверке счетчика семафора. Если счетчик содержит ненулевое значение, его значение декрементируется и потоку разрешается выполнение критического участка. В противном случае поток блокируется на семафоре до тех пор, пока не увеличится значение счетчика. Операция V инкрементирует значение счетчика, тем самым позволяя очередному потоку, заблокированному на семафоре, продолжить выполнение. В WIN32 операцию P над семафором выполняет функция WaitForSingleObject. Перед входом в критический участок, контролируемый семафором, поток должен вызвать эту функцию, передав ей в качестве параметра идентификатор объекта ядра семафор. Функция WaitForSingleObjectдекрементирует значение счетчика семафора, а если он равен нулю переводит объект ядра семафор в состояние nonsignaled. Операцию V над семафором выполняет функция ReleaseSemaphore, которая инкрементирует значение счетчика семафора и переводит объект ядра семафор в состояние signaled.
предыдущаяследующая