Vlákna
http://phoenix.inf.upol.cz/~outrata/courses/os2/texts/synch1_w.html
Windows - Synchronizace (Synchronization)
Win32 API poskytuje mnoho způsobů koordinace vykonávání více vláken a mechanizmů synchronizace přístupu k prostředku. První metoda je použití synchronizačních objektů v čekacích funkcích. Stav objektu je buď signalizován nebo nesignalizován. Čekací funkce blokují vykonávání vlákna, dokud není nesignalizovaný objekt signalizován. Další synchronizační mechanizmus je např. objekt kritické sekce.
Čekací funkce (Wait functions)
Existují tři typy čekacích funkcí: single-object, multiple-object a alertable. Tyto funkce se neukončí, dokud není splněna nějaká podmínka. Když je funkce zavolána, zkontroluje, zda je podmínka splněna. Pokud ne, vlákno vstoupí do čekacího stavu, kde spotřebovává velmi málo času procesoru a čeká, až bude podmínka splněna.
Single-object čekací funkce jsou WaitForSingleObject
a SignalObjectAndWait
.
WaitForSingleObject |
|
SignalObjectAndWait |
|
Multiple-object čekací funkce jsou WaitForMultipleObjects
a MsgWaitForMultipleObjects
.
WaitForMultipleObjects |
|
MsgWaitForMultipleObjects |
|
Před svým ukončením může čekací funkce změnit stav synchronizačního objektu, na který čekala, např. snížit hodnotu semaforu o 1 (ten je nesignalizován, pokud jeho hodnota je 0) nebo nastavit na nesignalizovaný stav mutex, auto-reset událost, change-notification objekt a synchronizační časovač.
Čekací funkce se musí používat opatrně ve spojení s DDE. Pokud vlákno vytvoří okno, musí obsluhovat zprávy. DDE posílá zprávy všem oknům v systému. Pokud vlákno čeká bez časového omezení, nastane deadlock. Vlákna, která tvoří okna, musí používat MsgWaitForMultipleObjects
.
Synchronizační objekty (Synchronization objects)
Synchronizační objekt se zadává (jeho handle) v čekacích funkcích ke koordinaci vykonávání více vláken. Stejný objekt může využívat i více procesů pro meziprocesní synchronizaci. Pro synchronizaci se používají objekty události, semaforu, mutexu a časovače. Ale mohou se použít i objekty procesu a vlákna, které jsou při běhu nesignalizovány a signalizovány při ukončení.
Objekt události (Event object)
Jsou dva typy objektu události:
- manual-reset - zůstane signalizován, dokud není explicitně nastaven na nesignalizován, když je signalizován, může se odblokovat libovolný počet čekajících vláken
- auto-reset - zůstane signalizován, dokud není odblokováno jedno čekající vlákno, objekt je pak nastaven na nesignalizován
Objekt události je užitečný pro zaslání signálu pro indikaci, že se objevila nějaká událost (např. se dokončila nějaká operace).
CreateEvent |
|
OpenEvent |
|
SetEvent |
|
PulseEvent |
|
ResetEvent |
|
Př. Napište program, ve kterém vytvoříte vlákno. Toto vlákno bude monitorovat stav objektu události a při signalizovaném stavu se ukončí. Objekt signalizujte z prvního vlákna.
Semafor (Semaphore object)
Semafor je "počítadlo", které má hodnotu od 0 do maximální hodnoty. Hodnota je dekrementována (o 1) po každé čekací funkci a inkrementována, když vlákno semafor uvolní. Když je hodnota 0, čekací funkce vlákno blokuje. Semafor je signalizován, když je jeho hodnota větší než 0, a nesignalizován, když je 0.
Semafor je užitečný ke kontrolování sdíleného prostředku, ke kterému má přístup omezený počet uživatelů. Např. limit na počet vytvořených oken. Maximální hodnota semaforu je maximální počet oken, dekrementuje se při vytvoření okna, inkrementuje při zavření. Před vytvořením okna se volá čekací funkce se semaforem.
CreateSemaphore |
|
OpenSemaphore |
|
ReleaseSemaphore |
|
Počáteční hodnota semaforu je typicky maximální hodnota. Je dekrementována při spotřebovávání chráněného prostředku. Nebo je počáteční hodnota 0 pro blokování přístupu během inicializace aplikace. Po inicializaci se hodnota zvedne na maximální hodnotu.
Vlákna nevlastní semafor. Při opakovaném čekání na semafor se tento vždy dekrementuje a při 0 se vlákno samo blokuje. Zvednout hodnotu semaforu může libovolné vlákno. Dekrementování o více než 1 se provede více voláními čekací funkce s tímto semaforem. Uvedení jednoho semaforu vícekrát v multiple-object čekací funkci ho dekrementuje pouze o 1.
Př. Napište program, ve kterém vytvoříte vlákno. Jedno vlákno bude něco zapisovat do společného bufferu (naplní ho), druhé z něho číst (vyprázdní ho). Synchronizujte tyto dvě vlákna semafory tak, aby se zapisovalo, jen když je buffer prázdný, a četlo, jen když je plný, a do bufferu v danou chvíli přistupovalo jen jedno vlákno.
Mutex (Mutex object)
Mutex je signalizován, když ho nevlastní žádné vlákno, a nesignalizován, když ho vlastní jedno vlákno. Mutex může vlastnit právě jedno vlákno, používá se k exkluzivnímu přístupu ke sdílenému prostředku (MUTtually EXclusive). Např. pro zabránění dvěma vláknům zápisu do sdílené paměti ve stejnou chvíli, obě čekají na vlastnictví objektu a pak jedno zapisuje, potom vlákno mutex uvolní.
CreateMutex |
|
OpenMutex |
|
Vlákno požaduje vlastnictví mutexu pomocí některé čekací funkce. Pokud již mutex vlastní jiné vlákno, čekací funkce vlákno blokuje, dokud to druhé vlákno mutex neuvolní. Když vlákno vlastní mutex, může ho použít v opakovaných voláních čekací funkce bez blokování (vlákno neblokuje samo sebe). Pro uvolnění mutexu ho musí uvolnit stejně počet-krát.
ReleaseMutex |
|
Př. Nahraďte patřičné semafory z předchozího příkladu mutexy.
Další funkce týkající se čekacích funkcí, objektů události, semaforů nebo mutexů jsou:
- WaitForSingleObjectEx
- WaitForMultipleObjectsEx
- MsgWaitForMultipleObjectsEx