Синхронизация потоков в операционной системе Windows, страница 12

                                                   // здесь расположен критический участок кода

LeaveCritica1Section(&section):

}

Другой вариант аналогичной функции:

BOOL only_one_at_a_time()

{ if(!TryEnterCriticalSection(&section))   // инициализация выполняется

                                                           // в другом месте

return FALSE:                                      // функция занята другим потоком

// здесь расположен критический участок кода

LeaveCnticalSection(&section);

return TRUE: // мы сделали это!

}

Если вы больше не нуждаетесь в критической секции, вы обратитесь к DeleteCnticalSection, чтобы уничтожить ее. При этом система освободит ресурсы, связанные с критической секцией.

В пакете добавлений NT 4.0 Service Pack 3 впервые появился еще один вызов, предназначенный для инициализации критической секции. Этот вызов под названием InitializeCriticalSectionAndSpinCount работает в точности так же, как и InitializeCriticalSection, если речь идет об однопроцессорной системе. Но если компьютер оснащен несколькими процессорами, новый системный вызов обладает некоторыми преимуществами. Обнаружив, что критическая секция уже занята другим потоком, ваш поток ждет некоторое небольшое количество времени, определяемое специальным счетчиком (spin count). Если после этого критическая секция все еще остается занятой, поток переходит в другой режим ожидания, напоминающий MaitForSingleObject. Значение специального счетчика можно установить для каждой критической секции при помощи вызова SetCriticalSectionSpinCount. He забывайте, что на однопроцессорных компьютерах эти вызовы не будут иметь эффекта.

Вызовы, связанные с критической секцией                                                    Таблица 5

Вызов

Назначение

InitializeCriticalSection InitializeCriticalSectionAndSpinCount

EnterCriticalSection

TryEnterCriticalSection

LeaveCriticalSection

SetCriticalSectionSpinCount

DeleteCriticalSection

Инициализирует переменную типа CRITICALSECTION Инициализирует переменную типа CRITICALSECTION и счетчик ее ожидания (см. текст)

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

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

Покидает критическую секцию, разрешая другим потокам войти в нее

Устанавливает значение счетчика ожидания критической секции (spin count)

Уничтожает переменную CRITICALSECTION

Другие объекты синхронизации

Помимо упомянутых существуют также другие типы объектов, за состоянием которых можно следить при помощи вызова MaitForSingleObject и аналогичных функций. На самом деле объекты, о которых пойдет речь, не являются объектами синхронизации в чистом виде, однако не упомянуть о них в рамках этой книги нельзя. На мой взгляд, лучше всего рассказать об этих объектах именно в этой главе. Вспомним, например, о вызовах, которые использовались в лабораторной работе про ПРОЦЕССЫ, ПОТОКИ и НИТИ для определения момента завершения процесса или потока. В отношении этих вызовов можно сказать, что в момент завершения процесса или потока дескриптор этого процесса или потока переходит в сигнальное состояние. Дескриптор процесса или потока не является объектом синхронизации, однако за его состоянием можно следить точно так же, как вы следите за состоянием любого объекта синхронизации.

Оповещение об изменениях

Оповещение об изменении (change notification) — это специальный объект, который переходит в сигнальное состояние в случае, если содержимое дискового каталога изменяется. Чтобы создать оповещение об изменении, необходимо обратиться к функции FindFirstChangeNotification. В качестве параметров функция принимает имя каталога и два флага. Первый флаг указывает на то, что поиск изменений будет осуществляться не только в указанном каталоге, но и во всех его подкаталогах. Второй флаг определяет набор событий, которым будет уделять внимание оповещение об изменениях. Например, можно следить за любым изменением файла, за изменением размера или времени записи любого файла и т. п.