ВУЗ:
Составители:
секция не является объектом ядра). Однако этот метод может использоваться только для синхронизации потоков одного
процесса.
Критическая секция – это некоторый участок кода, который в каждый момент времени может выполняться только од-
ним из потоков. Если код, используемый для инициализации массива, поместить в критическую секцию, то другие потоки не
смогут войти в этот участок кода до тех пор, пока первый поток не завершит его выполнение.
До использования критической секции необходимо инициализировать ее с помощью процедуры Win32 API
InitializeCriticalSection(), которая определяется (в Delphi) следующим образом:
procedure InitializeCriticalSection(var IpCriticalSection:
TRTLCriticalSection); stdcall;
Параметр IpCriticalSection представляет собой запись типа TRTLCriticalSection, которая передается по ссылке.
После заполнения записи в программе можно создать критическую секцию, поместив некоторый участок ее текста ме-
жду вызовами функций EnterCriticalSection() и LeaveCriticalSection(). Эти процедуры определяются следующим образом:
procedure EnterCriticalSection(var IpCriticalSection:
TRTLCriticalSection); stdcall;
procedure LeaveCriticalSection(var IpCriticalSection:
TRTLCriticalSection); stdcall;
Параметр IpCriticalSection, который передается этим процедурам, является не чем иным, как записью, созданной проце-
дурой InitializeCritical- Section().
Функция EnterCriticalSection проверяет, не выполняет ли уже какой-нибудь другой поток критическую секцию своей
программы, связанную с данным объектом критической секции. Если нет, поток получает разрешение на выполнение своего
критического кода, точнее, ему не запрещают это делать. Если да, то поток, обратившийся с запросом, переводится в состояние
ожидания, а о запросе делается запись. Так как нужно создавать записи, объект "критическая секция" представляет собой
структуру данных.
Когда функция LeaveCriticalSection вызывается потоком, который владеет в текущий момент разрешением на выполне-
ние своей критической секции кода, связанной с данным объектом "критическая секция", система может проверить, нет ли в
очереди другого потока, ожидающего освобождения этого объекта. Затем система может вынести ждущий поток из состоя-
ния ожидания, и он продолжит свою работу (в выделенные ему кванты времени).
По окончании работы с записью TRTLCriticalSection необходимо освободить ее, вызвав процедуру
DeleteCriticalSection(), которая определяется следующим образом:
procedure DeleteCriticalSection(var IpCriticalSection:
TRTLCriticalSection); stdcall;
Синхронизация с использованием объектов ядра. Многие объекты ядра, включая процесс, поток, файл, мьютекс, се-
мафор, уведомление об изменении файла и событие, могут находиться в одном из двух состояний – "свободно" (signaled) и
"занято" (nonsignaled). Вероятно, проще представлять себе эти объекты подключенными к лампочке. Если свет горит, объект
свободен, в обратном случае объект занят.
Например, в момент создания процесса его объект ядра находится в состоянии "занято". Когда процесс завершается,
объект переходит в состояние "свободно". Аналогично выполняющиеся потоки (т.е. их объекты) пребывают в состоянии
"занято", но переходят в состояние "свободно", когда завершают работу. На самом деле некоторые объекты, такие как мью-
текс, семафор, событие, уведомление об изменении файла, таймер ожидания, существуют исключительно для того, чтобы
вырабатывать сигналы "свободно" и "занято".
Смысл всей этой "сигнализации" в том, чтобы поток мог приостанавливать свою работу до того момента, когда задан-
ный объект перейдет в состояние "свободно". Например, поток одного процесса может временно прекратить работу до за-
вершения другого, просто подождав, когда объект ядра этого другого процесса перейдет в состояние "свободно".
Посредством вызова функций WaitForSingleObject и WaitForMultipleObjects поток приостанавливает свое выполнение
до того момента, когда заданный объект (или объекты) перейдет в состояние "свободно". Рассмотрим функции Wait-
ForSingleObject, декларация которой выглядит так:
DWORD WaitForSingleObject(
HANDLE hHandle, // Дескриптор объекта ожидания.
DWORD dwMilliseconds // Время ожидания в миллисекундах.
);
Параметр hHandle является дескриптором объекта, уведомление о свободном состоянии которого требуется получить, a
dwMilliseconds – это время, которое вызывающий поток готов ждать. Если dwMilliseconds равно нулю, функция немедленно
вернет текущий статус заданного объекта. Таким образом, можно протестировать состояние объекта. Параметру можно также
присваивать значение символьной константы INFINITE (= -1), в этом случае вызывающий поток будет ждать неограниченное
время.
Функция WaitForSingleObject переводит вызывающий поток в состояние ожидания до того момента, когда она передаст
ему свое возвращаемое значение, например:
WAIT_OBJECT_0 – объект находится в состоянии "свободно";
WAIT_TIMEOUT – интервал ожидания, заданный dwMilliseconds, истек, а нужный объект по прежнему находится в со-
стоянии "занято";
WAIT_ABANDONED относится только к мьютексу и означает, что объект не был освобожден потоком, который владел
им до своего завершения;
WAIT_FAILED – при выполнении функции произошла ошибка.
Страницы
- « первая
- ‹ предыдущая
- …
- 27
- 28
- 29
- 30
- 31
- …
- следующая ›
- последняя »