Содержание материала

 

Задача синхронизации встает при одновременном доступе нескольких процессов (или нескольких потоков одного процесса) к какому-либо ресурсу. Поскольку поток в Win32 может быть остановлен в любой, заранее ему неизвестный момент времени возможна ситуация, когда один из потоков не успел завершить модификацию ресурса (например, отображенной на файл области памяти), но был остановлен, а другой поток попытался обратиться к этому же ресурсу. В этот момент ресурс находится в несогласованном состоянии, и последствия обращения к нему могут быть самыми неожиданными от порчи данных, до нарушения защиты памяти.

Главной идеей, положенной в основу синхронизации потоков в Win32 является использование объектов синхронизации и функций ожидания. Объекты могут находиться в одном из двух состояний Signaled или Not Signaled. Функции ожидания блокируют выполнение потока до тех пор, пока заданный объект находится в состоянии Not Signaled. Таким образом, поток, которому необходим эксклюзивный доступ к ресурсу, должен выставить какой-либо объект синхронизации в несигнальное состояние, а по окончании сбросить его в сигнальное. Остальные потоки должны перед доступом к этому ресурсу вызвать функцию ожидания, которая позволит им дождаться освобождения ресурса.

Рассмотрим, какие объекты и функции синхронизации предоставляет нам Win32 API.

 

Функции синхронизации

Функции синхронизации делятся на две основные категории это функции, ожидающие единственного объекта и функции, ожидающие одного из нескольких объектов

 

Функции, ожидающие единственного объекта

Простейшей функцией ожидания является

 

function WaitForSingleObject(

hHandle: THandle;       // идентификатор объекта

dwMilliseconds: DWORD   // период ожидания

): DWORD; stdcall;

 

Функция ожидает перехода объекта hHandle в сигнальное состояние в течении dwMilliseconds миллисекунд. Если в качестве параметра dwMilliseconds передать значение INFINITE, функция будет ждать в течение неограниченного времени. Если dwMilliseconds равен 0, то функция проверяет состояние объекта и немедленно возвращает управление.

Функция возвращает одно из следующих значений:

WAIT_ABANDONED        Поток, владевший объектом, завершился, не переведя объект в сигнальное состояние.        

WAIT_OBJECT_0        Объект перешел в сигнальное состояние        

WAIT_TIMEOUT        Истек срок ожидания. Обычно в этом случае генерируется ошибка, либо функция вызывается в цикле до получения другого результата        

WAIT_FAILED        Произошла ошибка, например неверное значение hHandle. Более подробную информацию можно получить, вызвав GetLastError        

Следующий фрагмент кода запрещает Action1 до перехода объекта ObjectHandle в сигнальное состояние. Например, таким образом можно дожидаться завершения процесса, предав в качестве ObjectHandle его идентификатор, полученный функцией CreateProcess.

Code:

var

Reason: DWORD;

ErrorCode: DWORD;

 

Action1.Enabled := FALSE;

try

repeat

   Application.ProcessMessages;

   Reason := WailForSingleObject(ObjectHandle, 10);

   if Reason = WAIT_FAILED then begin

     ErrorCode := GetLastError;

     raise Exception.CreateFmt(

       'Wait for object failed with error: %d', [ErrorCode]);

   end;

until Reason <> WAIT_TIMEOUT;

finally

Actionl.Enabled := TRUE;

end;

 

 

В случае, когда требуется одновременно с ожиданием объекта, перевести в сигнальное состояние другой объект может использоваться функция:

 

function SignalObjectAndWait(

hObjectToSignal: THandle;  // объект, который будет переведен в

                            // сигнальное состояние

hObjectToWaitOn: THandle;  // объект, которого ожидает функция

dwMilliseconds: DWORD;     // период ожидания

bAlertable: BOOL           // задает, должна ли функция возвращать

                            // управление в случае запроса на

                            // завершение операции ввода-вывода

): DWORD; stdcall;

 

Возвращаемые значения аналогичны функции WaitForSingleObject.

! В модуле Windows.pas эта функция ошибочно объявлена, как возвращающая значение BOOL. Если Вы намерены её использовать объявите её корректно или используйте приведение типа возвращенного значения к DWORD

Объект hObjectToSignal может быть семафором, событием (event), либо мутексом. Параметр bAlertable определяет, будет ли прерываться ожидание объекта, в случае, если операционная система запросит у потока окончание операции асинхронного ввода-вывода, либо асинхронный вызов процедуры. Более подробно это обсуждается ниже.

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить