390 likes | 530 Views
Syn chroniz ácia procesov. Background Probl é m kritickej sekcie Peterson ovo riešenie Synchroniza čný h ard vér Sema fory K lasic ké p robl émy s ynchroniz ácie Monitor y Synchroniza čné príklady. Ciele.
E N D
Synchronizácia procesov • Background • Problém kritickej sekcie • Petersonovoriešenie • Synchronizačnýhardvér • Semafory • Klasicképroblémysynchronizácie • Monitory • Synchronizačné príklady
Ciele • Predstaviť problém kritickej sekcie,ktorej riešenia môžu byť použité na zabezpečenie konzistentnosti zdieľaných dát • Prezentovať ako hardvérové, tak aj softvérové riešenie problému kritickej sekcie
Background • Súbežný (paralelný) prístup k zdieľaným dátam môže vyústiť do nekonzistentnosti dát • Zachovanie konzistentnosti dát vyžaduje mechanizmy ktoré zabezpečia usporiadané vykonávanie spolupracujúcich procesov • Predpokladajme riešenie problémukonzument-producentPridáme celočíselnú premennú counter (count), inicializovanú nulou.Na začiatku, counter je nastavený na 0. Jeho hodnotu zvyšuje producentzavedením vyprodukovanej položky do bufru a znižuje ju konzument.
Producent while (true) { /* produkuj nejakú položku do nextProduced */ while (count == BUFFER_SIZE) ; // do nothing buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; }
Konzument while (true) { while (count == 0) ; // do nothing nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; /* konzumuj položku v nextConsumed }
Súbežný výpočet • count++môže byť implementovaný akoregister1 = count register1 = register1 + 1 count = register1 • count–môže byť implementovaný akoregister2 = count register2 = register2 - 1 count = register2 • Uvažujme nasledovné vykonanie, vychádzame z hodnoty counter “count = 5” S0: producent vykonáregister1 = count {register1 = 5}S1: producent vykonáregister1 = register1 + 1 {register1 = 6} S2: konzumentvykonáregister2 = count {register2 = 5} S3: konzumentvykonáregister2 = register2 - 1 {register2 = 4} S4: producentvykonácount = register1 {count = 6 } S5: konzumentvykonácount = register2 {count = 4}
Riešenia problému kritickej sekcie 1. Vzájomné vylúčenie– Ak procesPisa vykonáva vo svojej kritickej sekcii, potom žiadne iné procesy nemôžu byť vykonávané vo svojich kritických sekciách 2. Pokrok – Ak žiaden proces nie je vykonávaný vo svojej kritickej sekcii a niektoré procesy chcú vstúpiť do svojej kritickej sekcie, potom iba tie procesy, ktoré sú vykonávané vo svojich vstupných sekciách sa môžu zúčastniť na rozhodovaní, ktorým vstúpia do svojej kritickej sekcie a tento výber nemôže byť odložený natrvalo 3. Ohraničené čakanie- Existuje hranica na čas čakania procesu, t.j.rozdiel času, kedy proces žiadal o vstúpenie do svojej kritickej sekcie a času, kedy bola povolená táto požiadavka • Predpokladajme že každý proces je vykonávaný nenulovou rýchlosťou • Relatívnu rýchlosť medzi N procesmi neuvažujeme
Petersonovo riešenie • Riešenie 2 procesov • Predpokladajme, že LOAD a STORE inštrukcie sú atomické; to znamená, nemôžu byť prerušené. • Dva procesy zdieľajú dve premenné: • int turn; • Boolean flag[2] • Premennáturn indikujektoré (čie) turn vstupuje do kritickej sekcie • The flagpoleindikuje ak proces je pripravený vstúpiť do kritickej sekcie. flag[i] = true implikuje že procesPije pripravený(ready)!
Algoritmuspre Proces Pi do { flag[i] = TRUE; turn = j; while (flag[j] && turn == j); kritická sekcia flag[i] = FALSE; zvyšná sekcia } while (TRUE);
Synchronizačnýhardvér • Veľa systémov poskytuje hardvérovú podporu pre kód kritickej sekcie • Jednoprocesorové systémy – môžu zakázať prerušenia • Práve bežiaci kód môže byť vykonaný bez prerušenia • Všeobecne, toto riešenie je príliš neefektívne v multiprocesorovom systéme • Systémová výkonnosť klesá • Moderné stroje poskytujú špeciálnu atomickú hardvérovú inštrukciu – napr. „TestandSet“ inštrukcia • Atomický = neprerušiteľný • Dovoľujú testovať a modifikovať obsah slova alebo vymeniť obsahy 2 slov - atomicky • Alebo„swap“inštrukcia pracuje s obsahmi 2 slov
TestAndSet Inštrukcia • Definícia: boolean TestAndSet (boolean *target) { boolean rv = *target; *target = TRUE; return rv: }
Riešenie použitím TestAndSet • Zdieľaná booleovská premenná lock., inicializovaná na false. • Riešenie: do { while ( TestAndSet (&lock )) ; // do nothing // critical section lock = FALSE; // remainder section } while (TRUE);
Swap Inštrukcia • Definícia: void Swap (boolean *a, boolean *b) { boolean temp = *a; *a = *b; *b = temp: }
Riešenie použitím Swap • Zdieľaná globálna ooleovská premenná lock inicializovaná na FALSE; Každý proces má lokálnu booleovskú premennú key • Riešenie: do { key = TRUE; while ( key == TRUE) Swap (&lock, &key ); // kritická sekcia lock = FALSE; // zvyšná sekcia } while (TRUE);
Ohraničené čakanie a vzájomné vylučovanie v TestandSet() do { waiting[i] = TRUE; key = TRUE; while (waiting[i] && key) key = TestAndSet(&lock); waiting[i] = FALSE; // kritická sekcia j = (i + 1) % n; while ((j != i) && !waiting[j]) j = (j + 1) % n; if (j == i) lock = FALSE; else waiting[j] = FALSE; // zvyšná sekcia } while (TRUE);
Semafory • Synchronizačný prostriedok nevyžaduje aktívne (zamestnané) čakanie • SemaforS – integer premenná • Semafor premenná prístupná cez 2 štandardné operácieS: wait() and signal() • Pôvodne nazývanéP() aV() • Menej komplikované • Semafor môže byť prístupný len cez 2 štandardné atomické operácie • wait (S) { while S <= 0 ; // no-op S--; } • signal (S) { S++; }
Semafor ako všeobecný synchronizačný prostriedok • Počítacísemafor – jeho integer hodnota môže mať neobmedzený rozsah • Binárnysemafor – celočíselná hodnota, ktorá môže byť iba 0 alebo 1; môže byť jednoduchší z hľadiska implementácie • Tiež známy ako mutex locks • Je možné implementovať počítací semafor S ako binárny semafor • Poskytuje vzájomné vylučovanie (mutual exclusion) Semaphore mutex; // initialized to 1 do { wait (mutex); // Kritická sekcia signal (mutex); // Zvyšná sekcia } while (TRUE);
Implementácia semaforu • Musí byť zabezpečené, že žiadne 2 procesy nemôžu vykonávaťwait () a signal () na tom istom semafore v tom istom čase • Takto sa implementácia stáva problémom kritickej sekcie, kde wait a signal kódsú umiestnené v kritickej sekcii. • Implementácia zamestnaného čakania(busy waiting)v kritickej sekcii • Implementačný kód je krátky • Krátke aktívne čakanie ak kritická sekciajezriedka zamestnaná • Poznamenajme, že ak aplikáciemíňajú veľa času v kritickej sekcii, uvedené riešenie nie je dobré.
Implementácia semafora bez aktívneho (zamestnaného) čakania • Ku každému semaforu je pripojený front čakajúcich. Každý semafor vo fronte čakajúcich má 2 dátové položky: • celočíselnú hodnotu • zoznam procesov (ukazovateľ na nasledujúci záznam v zozname) • Dve operácie: • block – umiestni proces,ktorý vyvolal operáciu do vhodného frontu čakajúcich. • wakeup – premiestni 1 z procesov z frontu čakajúcich a umiestni ho do frontu pripravených.
Implementácia semaforabez aktívneho (zamestnaného) čakania • Implementácia „wait“: wait(semaphore *S) { S->value--; if (S->value < 0) { add this process to S->list; block(); } } • Implementácia„signal“: signal(semaphore *S) { S->value++; if (S->value <= 0) { remove a process P from S->list; wakeup(P); } }
Uviaznutie a hladovanie • Uviaznutie (deadlock)– dvaalebo viac procesov čakajú natrvalo na udalosť, ktorá môže byť zapríčinenáiba jedným z čakajúcich procesov • NechS a Qsú dva semafory inicializované na 1 P0P1 wait (S); wait (Q); wait (Q); wait (S); . . . . . . signal (S); signal (Q); signal (Q); signal (S); • Hladovanie (starvation)– nekonečné blokovanie. Proces čaká natrvalo vo vnútri semaforu • Zmena priority- Plánovací problem kedy proces nižšej priority drží zámok potrebný pre proces vyššej priority
Klasicképroblémysynchronizácie • Problém ohraničený zásobník • Problém čitatelia - zapisovatelia • Problém obedujúci filozofovia
Problém ohraničený zásobník • Nzásobníkov, každý zásobník je schopný držať 1 položku • Semaformutexje inicializovaný na hodnotu 1, poskytuje vzájomné vylučovanie pre prístup do sady zásobníkov • Semaforfull je inicializovaný na hodnotu 0, počíta počet plných zásobníkov • Semaforemptyje inicializovaný na hodnotu N, počíta počet prázdnych zásobníkov
Problém ohraničený zásobník • Štruktúra procesu „producent“ do { // produkuj nejakú položku do nextproduced wait (empty); wait (mutex); // pridaj nextproduced do zásobníka signal (mutex); signal (full); } while (TRUE);
Problém ohraničeného zásobníka • Štruktúra procesu „konzument“ do { wait (full); wait (mutex); // vyber (premiestni) položku zo zásobníka do nextconsumed signal (mutex); signal (empty); // konzumujpoložku v nextconsumed } while (TRUE);
Problém čitatelia-zapisovatelia • Množina dát (dátový objekt) je zdieľaný medzi viacerými súbežnými procesmi • Čitatelia– iba čítajú obsah zdieľaného objektu; nemôžu vykonávať žiadne úpravy, zmeny • Zapisovatelia – môžu aj čítať aj zapisovať • Problém – dovoliť viacerým čitateľom čítať v rovnakom čase. Iba jeden zapisovateľ môže mať prístup k zdieľaným dátam v danom čase. • Zdieľanédáta • Dátový objekt • Semaformutex inicializovaný na 1 • Semaforwrt inicializovaný na 1 • Integer readcount inicializovaný na 0
Problém čitatelia - zapisovatelia • Štruktúra procesu „zapisovateľ“ do { wait (wrt) ; // zápis je vykonaný signal (wrt) ; } while (TRUE);
Problém čitatelia - zapisovatelia • Štruktúra procesu „čitateľ“ do { wait (mutex) ; readcount ++ ; if (readcount == 1) wait (wrt) ; signal (mutex) // čítanie je vykonané wait (mutex) ; readcount - - ; if (readcount == 0) signal (wrt) ; signal (mutex) ; } while (TRUE);
Problém obedujúcich filozofov • Zdieľané dáta • Misa ryže (dátový objekt) • Semaforpalička [5] inicializovaný na 1
Problém obedujúcich filozofov • Štruktúra filozofa i: do { wait ( palička[i] ); wait ( palička[ (i + 1) % 5] ); // jedenie signal ( palička[i] ); signal (palička[ (i + 1) % 5] ); // myslenie } while (TRUE);
ProblémysosemaformiKritické regióny • Nesprávne použitie operácií v semafore: • signal (mutex) …. wait (mutex) • wait (mutex) … wait (mutex) • Vynechanie wait (mutex) alebo signal (mutex) (alebo oboch)
Monitory • Synchronizačná konštrukcia vyššej úrovne ktorá poskytuje pohodlný a efektívny mechanizmuspresynchronizáciu procesov, je to množina operátorov definovaných programátorom • Iba jeden proces v danom čase môže byť aktívny vo vnútri monitora, reprezentácia (syntax) monitora je nasledovná: monitor monitor-meno { // deklarovanie zdieľaných premenných procedure body P1 (…) { …. } … procedure body Pn (…) {……} Inicializačný kód ( ….) { … } … } }
Premenné typu Condition • condition x, y; • Jediné 2 operácie, ktoré môžu byť vyvolané na premennej typu „condition“ sú: • x.wait () – proces,ktorý spôsobí vyvolanie tejto operácie je pozastavený, až kým iný proces vyvolá x.signal () . • x.signal () –táto operácia obnoví presne 1 pozastavený proces vyvolaný x.wait ()
Riešenie pomocou obedujúcich filozofov monitor dp { enum { MYSLIACI, HLADNÝ;JEDIACI) stav [5] ; condition filozof [5]; void zober (int i) { sta[i] = HLADNY; test(i); if (stav[i] != JEDIACI) filozof [i].wait; } void polož (int i) { stav[i] = MYSLIACI; // testuj laveho a pravého suseda test((i + 4) % 5); test((i + 1) % 5); }
Riešenie pomocou obedujúcich filozofov void test (int i) { if ( (stav[(i + 4) % 5] != JEDIACI) && (stav[i] == HLADNY) && (stav[(i + 1) % 5] != JEDIACI) ) { stav[i] = JEDIACI ; filozoff[i].signal () ; } } initialization_code() { for (int i = 0; i < 5; i++) stav[i] = MYSLIACI; } }
Riešenie pomocou obedujúcich filozofov • Distribúcia paličiek je riadená monitorom dp, ktorého definícia je ukázaná v predošlom. Každý Filozofi vyvolá operáciezober() a polož()v nasledujúcej postupnosti: dp.zober (i); JEDENIE dp.polož (i);
Implementácia Monitorupoužitím Semaforov • Premenné semaphore mutex; // (initially = 1) semaphore next; // (initially = 0) int next-count = 0; • Každá procedúraF bude premiestnená wait(mutex); … body of F; … if (next_count > 0) signal(next) else signal(mutex); • Mutual exclusion vo vnútri monitora je zabezpečené.