пользователей: 30398
предметов: 12406
вопросов: 234839
Конспект-online
РЕГИСТРАЦИЯ ЭКСКУРСИЯ

Синхронизация потоков. Другие функции, применяемые при синхронизации потоков

В среде, позволяющей исполнять несколько потоков одновременно, очень важно синхронизировать их деятельность.

Общий принцип синхронизации заключается в следующем: синхронизируемый поток «засыпает» до тех пор, пока не наступит определенное событие. Это событие определяет  сам поток и сообщает его ОС. Таким образом, поток синхронизирует свое выполнение с наступлением особого события.

В ОС предусмотрен ряд способов для синхронизации выполнения потоков, которые будут рассмотрены ниже:

управление приоритетами потоков;

wait-функции;

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

специальные объекты ядра.

Можно рассматривать понятия «свободен-занят» по аналогии с обыкновенным флажком Когда объект свободен, флажок поднят, а когда он занят, флажок опущен.

Потоки спят, пока ожидаемые ими объекты заняты (флажок опущен). Как только объект освободился (флажок поднят), спящий поток замечает это, просыпается и возобновляет выполнение. 

 
1.Асинхронный ввод-вывод на устройствах
2.Функция Sleep (см. выше)
3.Функция WaitForlnputldle
4.Функция MsgWaitForMultipleObjects(Ex)
5.Функция WaitForDebugEvent
6.Функция SignalObjectAndWait
 
Асинхронный ввод-вывод на устройствах
lПри асинхронном вводе-выводе поток начинает операцию чтения или записи и не ждет ее окончания.
lНапример, если потоку нужно загрузить в память большой файл, он может сообщить системе сделать это за него. И пока система грузит файл в память, поток спокойно занимается другими задачами — создает окна, инициализирует внутренние структуры данных и т. д. Закончив, поток приостанавливает себя и ждет уведомления от системы о том, что загрузка файла завершена.
lОбъекты устройств являются синхронизируемыми объектами ядра, а это означает, что можно вызывать WaitForSingleObject и передавать ей описатель какого-либо файла, сокета, коммуникационного порта и т. д. Пока система выполняет асинхронный ввод-вывод, объект устройства пребывает в занятом состоянии. Как только операция заканчивается, система переводит объект в свободное состояние, и поток узнает о завершении операции. С этого момента поток возобновляет выполнение.
 
Функция WaitForlnputldle
lПоток может приостановить себя вызовом:

DWORD WaitForInputIdle( HANDLE hProcess, DWORD dwMilliseconds);

lЭта функция ждет, пока у процесса, идентифицируемого описателем hProcess, не опустеет очередь ввода в потоке, создавшем первое окно приложения.
lЭту функцию можно применить и в том случае, когда нужно имитировать в программе нажатие каких-либо клавиш:
lWM_KEYDOWN с виртуальной клавишей VK_MENU
WM_KEYDOWN с виртуальной клавишей VK_F
WM_KEYUP с виртуальной клавишей VK_F
WM_KEYUP с виртуальной клавишей VK_MENU
WM_KEYDOWN с виртуальной клавишей VK_O
WM_KEYUP с виртуальной клавишей VK_O
 
Функция MsgWaitForMultipleObjects(Ex)
lПри вызове MsgWaitForMultipleObjects или MsgWaitForMultipleObjectsEx поток переходит в ожидание своих (предназначенных этому потоку) сообщений:

DWORD MsgWaitForMultipleObjects( DWORD dwCount, PHANDLE phObjects, BOOL fWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask);

DWORD MsgWaitForMultipleObjectsEx( DWORD dwCount, PHANDLE phObjects, DWORD dwMillisGConds, DWORD dwWakeMask DWORD dwFlags);

lОтличие от Wait… заключается в том, что эти функции пробуждают поток, когда освобождается некий объект ядра или когда определенное оконное сообщение требует перенаправления в окно, созданное вызывающим потоком.
lПоток, который создает окна и выполняет другие операции, относящиеся к пользовательскому интерфейсу, должен работать с функцией MsgWait…, а не с Wait…, так как последняя не дает возможности реагировать на действия пользователя
 
Функция WaitForDebugEvent
lВ Windows встроены богатейшие отладочные средства.
lНачиная исполнение, отладчик подключает себя к отлаживаемой программе, а потом просто ждет, когда операционная система уведомит его о каком-нибудь событии отладки, связанном с этой программой.
lОжидание таких событий осуществляется через вызов

BOOL WaitForDebugEvent(PDEBLIG_F_VENT pde, DWORD dwMimseconds);

lКогда отладчик вызывает WaitForDebugEvent, его поток приостанавливается.
lСистема уведомит поток о событии отладки, разрешив функции WaitForDebugEvent вернуть управление.
lСтруктура, на которую указывает параметр pdе, заполняется системой перед пробуждением потока отладчика. В ней содержится информация, касающаяся только что произошедшего события отладки.
 
Функция SignalObjectAndWait
lSignalObjectAndWait переводит в свободное состояние один объект ядра и ждет другой объект ядра, выполняя все это как одну операцию на уровне атомарного доступа:

DWORD SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL fAlertable);

lФункция проверяет тип объекта и выполняет действия, аналогичные тем, которые предпринимают функции ReleaseMutex, ReleaseSemaphore (со счетчиком, равным 1) или ResetEvent.
lhObjectToSignal должен идентифицировать мьютекс, семафор или событие; объекты любого другого типа заставят SignalObjectAndWait вернуть WAIT_FAILED, а функцию GetLastError – ERROR_INVALIDHANDLE.
lhObjectToWaitOn идентифицирует любой из следующих объектов ядра: мьютекс, семафор, событие, таймер, процесс, поток, задание, уведомление об изменении файла или консольный ввод.
ldwMilliseconds определяет, сколько времени функция будет ждать освобождения объекта, a флаг fAlertable указывает, сможет ли поток в процессе ожидания обрабатывать посылаемые ему АРС-вызовы.
lФункция возвращает одно из следующих значений: WAIT_OBJECT_0, WAIT_TIMEOUT, WAIT_FAILED, WATT_ABANDONED или WAIT_IO_COMPLETION.
lSignalObjectAndWait — удачное добавление к Windows API по двум причинам.
lBo-первых, освобождение одного объекта и ожидание другого — задача весьма распространенная, а значит, объединение двух операций в одной функции экономит процессорное время. Каждый вызов функции, заставляющей поток переходить из кода, который работает в пользовательском режиме, в код, работающий в режиме ядра, требует примерно 1000 процессорных тактов (на платформах x86), SignalObjectAndWait дает заметную экономию процессорного времени.
lВо-вторых, без функции SignalObjectAndWait ни у одного потока не было бы возможности узнать, что другой поток перешел в состояние ожидания.
 

26.12.2015; 23:26
хиты: 1
рейтинг:0
для добавления комментариев необходимо авторизироваться.
  Copyright © 2013-2024. All Rights Reserved. помощь