Windows - Synchronizace (Synchronization)

Synchronizace procesů (Interprocess synchronization)

Více procesů může mít handly objektu události, semaforu, mutexu nebo časovače, proto mohou být tyto prostředky použity i pro synchronizaci procesů. Proces, který objekt vytvoří, používá handle, který vrátí vytvářecí funkce. Ostatní procesy si handle otevřou použitím jeho jména nebo pomocí zdědění nebo duplikace handlu.

Jméno objektu může obsahovat jakékoliv znaky kromě zpětného lomítka \ a je case-sensitive. Jména objektů události, semaforu, mutexu, časovače a mapování souboru sdílejí stejný prostor jmen, proto by se pro tyto objekty měla používat unikátní jména. Pokud se při vytvoření objektu zadá jméno objektu jiného typu, vytvářecí funkce bude úspěšná, ale jméno zůstane původnímu objektu (a funkce GetLastError vrátí ERROR_ALREADY_EXISTS), např. v CreateMutex jméno semaforu. Při zadání jména objektu stejného typu vrátí vytvářecí funkce handle tohoto objektu, např. v CreateMutex jméno mutexu.
Při vytvoření procesu (pomocí funkce CreateProcess) lze specifikovat zdědění handlu objektu pomocí struktury SECURITY_ATTRIBUTES. Zděděný handle má stejná práva k objektu jako původní handle. Handle se sice zdědí, ale novému procesu se musí nějak sdělit jeho hodnota (např. přes parametr příkazové řádky).
Duplikaci handlu provádí funkce DuplicateHandle, hodnota nového handlu se musí nějak sdělit jinému procesu, libovolnou metodou meziprocesní komunikace (např. pojmenovanou rourou nebo přes sdílenou paměť).

Př. Synchronizujte programy ze cvičení 'Windows - Meziprocesní komunikace', část 'Mapování souboru'. Použijte jeden binární semafor tak, aby druhý program četl, až tam první něco zapíše.

Objekt kritické sekce (Critical section object)

Objekt kritické sekce poskytuje podobnou synchronizaci jako mutex s tím rozdílem, že se může použít pouze pro vlákna v jednom procesu. Mutexy lze takto také použít, ale objekt kritické sekce je rychlejší. Jako mutex, objekt kritické sekce vlastní v daném čase jen jedno vlákno a používá se pro ochranu sdílené proměnné proti vícenásobnému přístupu (s proměnnou se pracuje v tzv. kritické sekci).

InitializeCriticalSection
  • inicializuje objekt kritické sekce (typu CRITICAL_SECTION) na adrese lpCriticalSection
  • objekt nelze přesouvat, kopírovat nebo modifikovat

EnterCriticalSection
  • vlákno si přivlastní objekt kritické sekce (lpCriticalSection), tj. vstoupí do kritické sekce
  • pokud již objekt vlastní jiné vlákno, funkce blokuje (nekonečně dlouho)
  • opakované volání neblokuje (vlákno nezablokuje samo sebe), pro uvolnění se musí uvolnit stejně počet-krát

TryEnterCriticalSection
  • jako EnterCriticalSection, ale neblokuje
  • vrací nenulovou hodnotu, pokud vlákno vstoupí (nebo již je) v kritické sekci, pokud objekt vlastní jiné vlákno, vrací 0

LeaveCriticalSection
  • uvolní objekt kritické sekce (lpCriticalSection) z vlastnictví, tj. opustí kritickou sekci
  • pokud vlákno objekt nevlastní, vznikne chyba, která může způsobit nekonečné čekání na vlastnictví tohoto objektu

DeleteCriticalSection
  • zruší objekt kritické sekce (lpCriticalSection), který nevlastní žádné vlákno (žádné vlákno není v kritické sekci), a uvolní prostředky systému
  • může ji zavolat libovolné vlákno procesu, nejen to, které objekt inicializovalo

Pokud objekt kritické sekce vlastní nějaké vlákno (vlákno je v kritické sekci), blokována jsou pouze vlákna, která čekají na vlastnictví tohoto objektu (na funkci EnterCriticalSection), ostatní vlákna normálně pokračují (a mohou vykonávat i kritickou sekci prvního vlákna!).

Př. Napište program, ve kterém vytvoříte nové vlákno, jehož hlavní funkce bude mít 2 parametry, řetězce, které funkce spojí a výsledek vypíše. Spojení uzavřete do kritické sekce.

Další funkce týkající se synchronizace procesů nebo objektu kritické sekce jsou:



Jan Outrata
outrata@phoenix.inf.upol.cz