Синхронізація процесівСинхронізація процесів в інформатиці — приведення двох або декількох процесів або потоків (нитей) до такого їхнього протікання, коли певні стадії різних процесів здійснюються в певному порядку, або одночасно, для уникнення конкуренції потоків або взаємного блокування. Загальна ідея полягає в тому, що в певних точках процесам необхідно разом домовитися про певний порядок дій зі спільними ресурсами. Синхронізація необхідна у випадках, коли паралельно протікаючим процесам (або потокам одного процесу) необхідна взаємодія. Засоби синхронізаціїНайпоширеніші засоби синхронізації такі:
Синхронізація у WindowsДля синхронізації потоків у Windows передбачено ряд функцій синхронізації. Синхронізація з одним об'єктомНайпростішою функцією, яка очікує завершення переходу заданого об’єкта у сигнальний стан, є WaitForSingleObject. DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds ); function WaitForSingleObject( hHandle: THandle; // Дескриптор об’єкта dwMilliseconds: DWORD // Час очікування ): DWORD; Функція очікує переходу об'єкта з дескриптором hHandle у сигнальний стан протягом dwMilliseconds мілісекунд. Якщо цим параметром передати значення INFINITE, функція буде чекати протягом необмеженого часу. Якщо dwMilliseconds дорівнює 0, то функція перевіряє стан об'єкта й негайно повертає керування. Дескриптор повинен бути відкритий з правом доступу SYNCHRONIZE. Функція повертає одне з перелічених у таблиці значень.
Приклад використання функції WaitForSingleObjectТут подано приклад коду, який створює новий процес, запускаючи стандартний текстовий редактор "Блокнот" (Notepad), і чекає на його завершення (приклад подано мовою Delphi)[2]. var
PI : TProcessInformation;
SI : TStartupInfo;
begin
(* ............................ *)
FillChar(SI, Sizeof(SI), #0);
SI.cb := SizeOf(SI);
if not CreateProcess('c:\windows\system32\notepad.exe', nil, nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, SI, PI) then
MessageBox(Handle, 'Не вдалося створити процес.', '',
MB_OK or MB_ICONERROR);
WaitForSingleObject(PI.hProcess, INFINITE);
Синхронізація кількох об'єктівДля синхронізації кількох об'єктів використовують фунцію API WaitForMultipleObjects. ЇЇ опис мовою C[3]: DWORD WINAPI WaitForMultipleObjects( __in DWORD nCount, __in const HANDLE *lpHandles, __in BOOL bWaitAll, __in DWORD dwMilliseconds ); function WaitForMultipleObjects( nCount: DWORD; // Кількість об’єктів lpHandles: PWOHandleArray; // Адреса масиву об’єктів bWaitAll: BOOL; // Чи чекати всі об’єкти dwMilliseconds: DWORD // Період очікування ): DWORD; Вказівник lpHandles посилається на масив, який містить дескриптори об’єктів очікування. Параметр nCount задає кількість елементів цього масиву. Якщо параметру bWaitAll задати значення true, функція очікуватиме на перехід у сигнальний стан усіх перелічених у масиві lpHandles об’єктів. Коли цей параметр дорівнює false, функція чекатиме на сигнальний стан одного з них. Параметр dwMilliseconds задає час очікування (як для функції WaitForSingleObject). Дескриптори повинні мати право доступу SYNCHRONIZE. Функція повертає одне з перелічених у таблиці значень.
Приклад очікування кількох об'єктівОчікування на завершення роботи трьох потоків з відомими дескрипторами (hThreadX) можна реалізувати так (код мовою Delphi)[2]: var Handles : array[0..2] of THandle; ............................................ Handles[0] := hThread1; Handles[1] := hThread2; Handles[2] := hThread3; WaitForMultipleObjects(3, @Handles, true, INFINITE); Очікування з обробкою повідомленьФункції WaitForSingleObject та WaitForMultipleObjects повністю зупиняють роботу викликаючого потоку, включаючи й стандартну обробку повідомлень графічної підсистеми Windows, тому програма не може навіть перемалювати своє вікно. Тому функції WaitForSingleObject та WaitForMultipleObjects варто використовувати, коли час очікування невеликий. Якщо ж затримка значна, слід дати можливість програмі обробляти деякі системні повідомлення. Для цього можна використати функцію MsgWaitForMultipleObjects. Її опис мовою C[4]: DWORD WINAPI MsgWaitForMultipleObjects( __in DWORD nCount, __in const HANDLE *pHandles, __in BOOL bWaitAll, __in DWORD dwMilliseconds, __in DWORD dwWakeMask ); function MsgWaitForMultipleObjects( nCount: DWORD; // Кількість об’єктів синхронізації var pHandles; // Адреса масиву об’єктів fWaitAll: BOOL; // Чи чекати на всі об’єкти dwMilliseconds, // Період очікування dwWakeMask: DWORD // Тип події, яка перериває очікування ): DWORD; Основна відмінність цієї функції від функції WaitForMultipleObjects – параметр dwWakeMask, який є комбінацією бітових прапорів QS_XXX і задає типи повідомлень, які перериватимуть очікування незалежно від стану очікуваних об'єктів. Наприклад, маска QS_KEY дозволяє перервати очікування з появою в черзі повідомлень від клавіатури, маска QS_MOUSE забезпечує реакцію на повідомлення миші, а маска QS_PAINT – повідомлення перемальовування WM_PAINT. З появою в черзі викликаючого потоку повідомлень, які відповідають заданій масці, функція повертає значення WAIT_OBJECT_0 + nCount. Отримавши таке значення, програма може обробити його й знову викликати функцію очікування. ПриміткиДивись також
|
Portal di Ensiklopedia Dunia