Сен 27 2010

Критические секции

Критическая секция (critical section) — это небольшой участок кода, который должен использоваться только одним потоком одновременно. Если в одно время несколько потоков попытаются получить доступ к критическому участку, то контроль над ним будет предоставлен только одному из потоков, а все остальные будут переведены в состояние ожидания до тех пор, пока участок не освободится.
Для использования критической секции необходимо определить переменную типа CRITICAL_SECTION:
CRITICAL_SECTION cs;
Поскольку эта переменная должна находиться в области видимости для каждого использующего ее потока, обычно она объявляется как глобальная. Эту переменную следует инициализировать до ее первого применения с помощью функции InitializeCriticalSection:
InitializeCriticalSection(Scs);
Чтобы завладеть критическим участком, поток должен вызвать функцию EnterCriticalSection:
EnterCri ti calSecti on(&cs);
Если критический участок не используется в данный момент другим потоком, он обозначается системой как занятый, и поток немедленно продолжает выполнение. Если критический участок уже используется, то поток блокируется до тех пор, пока участок не будет освобожден.
После вызова EnterCriticalSection следуют инструкции, принадлежащие критическому участку.
Конец критического участка обозначается вызовом функции LeaveCriticalSection:
LeaveCriticalSection(&cs);
Как только поток получает контроль над критическим участком, доступ других потоков к этому участку блокируется. При этом очень важно, чтобы время выполнения критического участка было минимальным. Это позволит добиться наилучших результатов работы приложения.
Если критический участок больше не нужен, используемые им ресурсы освобождаются вызовом функции DeleteCriticalSection.


Сен 05 2010

Побочные эффекты успешного ожидания

Успешный вызов функции WaitForSingleObject или WaitForMuttipleObjects на самом деле меняет состояние некоторых объектов ядра. Успешным считается такой вызов, который завершается освобождением соответствующего объекта или объектов. При этом функция возвращает значение WAIT_OBJECT_0 или значение, являющееся смещением относительно WAIT_OBJECT_0. Вызов считается неудачным, если возвращается значение WAIT_TIMEOUT или WAIT_FAILED. В этом случае состояние каких-либо объектов не меняется.
Пусть, например, поток вызвал функцию WaitForSingleObject и ждет освобождения объекта «событие с автосбросом» (объекты-события рассматриваются в следующем разделе). Когда объект переходит в свободное состояние, функция обнаруживает это и возвращает значение WAIT_OBJECT_0. Но перед самым возвратом из функции объект-событие будет переведен в занятое состояние. Это и есть побочный эффект успешного ожидания.
Объекты ядра «событие с автосбросом» ведут себя подобным образом, потому что таково одно из правил, определенных Microsoft для объектов этого типа. Другие объекты дают иные побочные эффекты, а некоторые — вообще никаких. К последним относятся объекты ядра «процесс» и «поток».