synchroniz ácia procesov

Post on 10-Jan-2016

72 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Synchroniz ácia procesov. Background. Súbežný prístup k zdieľaným dátam môže viesť k ich nekoexistencii Zabezpečenie koexistencie dát pri vzájomnej spolupráci procesov si vyžaduje zaoberať sa mechanizmami synchronizácie prístupu k zdieľaným dátam - PowerPoint PPT Presentation

TRANSCRIPT

©2009Operačné systémy

Synchronizácia procesov

6.2 ©2009Operačné systémy

Background

Súbežný prístup k zdieľaným dátam môže viesť k ich nekoexistencii

Zabezpečenie koexistencie dát pri vzájomnej spolupráci procesov si vyžaduje zaoberať sa mechanizmami synchronizácie prístupu k zdieľaným dátam

Predpokladajme že chceme poskytnúť riešenie problému konzument – producent ktorý zapĺňa všetky „buffers“. Môžeme to urobiť na základe počítadla celého čísla, ktoré uchováva počty plných „buffers“. Najprv je počítadlo (premenná count) nastavené na 0. Zaznamenáva prírastok od producenta, ktorý vytvorí nový bufer. Stav počítadla sa znižuje v dôsledku činnosti konzumenta, ktorý spotrebuje bufer.

6.3 ©2009Operačné systémy

Producent

while (true) {

/* produce an item and put in nextProduced */

while (count == BUFFER_SIZE)

; // do nothing

buffer [in] = nextProduced;

in = (in + 1) % BUFFER_SIZE;

count++;

}

6.4 ©2009Operačné systémy

Konzument

while (true) {

while (count == 0)

; // do nothing

nextConsumed = buffer[out];

out = (out + 1) % BUFFER_SIZE;

count--;

/* consume the item in nextConsumed

}

6.5 ©2009Operačné systémy

Súbeh

(count++) implementované môže byť nasledovne

register1 = count register1 = register1 + 1 count = register1

count-- implementované môže byť nasledovne

register2 = počítadlo register2 = register2 - 1 počítadlo = register2

Uvažujme toto vykonanie vložením “count = 5” prvotne:

S0: producent vykonáva register1 = count {register1 = 5}S1: producent vykonáva register1 = register1 + 1 {register1 = 6} S2: konzument vykonáva register2 = count {register2 = 5} S3: konzument vykonáva register2 = register2 - 1 {register2 = 4} S4: producent vykonáva count = register1 {count = 6 } S5: consumer execute count = register2 {count = 4}

6.6 ©2009Operačné systémy

Riešenie problému kritickej sekcie

1. Vzájomné vylúčenie – Ak proces Pi je vykonávaný v jeho kritickej sekcii, potom žiadny iný proces nemôže vstúpiť do svojej kritickej sekcie

2. Postup – Ak žiadny proces nie je vykonávaný vo svojej kritickej sekcii a je tu viac požiadaviek od procesov na vstup do ich kritickej sekcie, potom jednému z procesov bude povolené vstúpiť do kritickej sekcie. Výber procesu, ktorý dostane prístup, nesmie trvať nekonečne dlho.

3. Spravodlivosť - Žiadny proces nesmie nekonečne dlho brániť iným procesom vstúpiť do kritickej sekcie, t.j. každý proces musí mať rovnakú šancu vstúpiť do nej.

Predpokladáme, že každý proces sa vykonáva nenulovou rýchlosťou

Neexistuje žiadny predpoklad týkajúci sa relatívnej rýchlosti N procesov

6.7 ©2009Operačné systémy

Petersonovo riešenie

Dvojprocesorové riešenie (Two process solution) Predpokladajme, že inštrukcie LOAD a STORE sú atomické; t.j.,

nesmú byť prerušené. Atomická operácia je taká operácia, ktorá nemôže byť prerušená, musí sa vykonať len celá.

Dva procesy zdieľajú dve premenné: int turn; Boolean flag[2]

Premenná turn indikuje ktorý proces je na rade pre vstup do kritickej sekcie.

Prvky poľa sú inicializované na false. Pole indikátorov flag sa používa na indikovanie toho, ak proces je pripravený vstúpiť do kritickej sekcie. Ak flag[i] = true - proces Pi je pripravený vstúpiť do kritickej sekcie.

6.8 ©2009Operačné systémy

do {

flag[i] = TRUE;

turn = j;

while (flag[j] && turn == j);

critical section

flag[i] = FALSE;

remainder section

} while (TRUE);

Algoritmus pre proces Pi

6.9 ©2009Operačné systémy

Synchronizačný Hardware

Veľa systémov ponúka hardvérovú podporu pre kód kritickej sekcie. Jednoprocesory – mohli by zakázať prerušenia

Práve vykonávaný programový kód (bežiaci) bol by vykonávaný bez preempcie

Všeobecne, príliš neúčinné na multiprocesorových systémoch Operačné systémy používajúce toto nie sú široko

škálovateľné Moderné stroje ponúkajú špeciálne atomické hardwerové inštrukcie

Atomic = non-interruptable Buď testuj pamäťové slovo a nastav hodnotu Alebo vymeň obsahy dvoch pamäťových slov

6.10 ©2009Operačné systémy

Riešenie problému kritickej sekcie použitím zámku

do {

acquire lock

critical section

release lock

remainder section

} while (TRUE);

6.11 ©2009Operačné systémy

TestAndSet Inštrukcia

Definition:

boolean TestAndSet (boolean *target)

{

boolean rv = *target;

*target = TRUE;

return rv:

}

6.12 ©2009Operačné systémy

Riešenie použitím TestAndSet

Zdieľaná booleovská premenná lock., inicializovaná na hodnotu false. Riešenie:

do {

while ( TestAndSet (&lock ))

; // do nothing

// critical section

lock = FALSE;

// remainder section

} while (TRUE);

6.13 ©2009Operačné systémy

Swap Inštrukcia

Definícia:

void Swap (boolean *a, boolean *b)

{

boolean temp = *a;

*a = *b;

*b = temp:

}

6.14 ©2009Operačné systémy

Riešenie použitím Swap

Zdieľaná booleovská premenná lock inicializovaná na hodnotu FALSE; Každý proces má lokálnu booleovu premennú key

Riešenie:

do {

key = TRUE;

while ( key == TRUE)

Swap (&lock, &key );

// critical section

lock = FALSE;

// remainder section

} while (TRUE);

6.15 ©2009Operačné systémy

Ohraničené čakanie a vzájomné vylučovanie s TestandSet

do {

waiting[i] = TRUE;

key = TRUE;

while (waiting[i] && key)

key = TestAndSet(&lock);

waiting[i] = FALSE;

// critical section

j = (i + 1) % n;

while ((j != i) && !waiting[j])

j = (j + 1) % n;

if (j == i)

lock = FALSE;

else

waiting[j] = FALSE;

// remainder section

} while (TRUE);

6.16 ©2009Operačné systémy

Semafory

Synchronizačné prostriedky ktoré nevyžadujú aktívne, zamestnané čakanie (does not require busy waiting)

Semafor S – je celočíselná (integer) premenná Okrerm inicializácie je prístupná len cez dve štandardné operácie ktoré modifikujú

S: wait() a signal()

Pôvodne nazývané P() a V() Menej komplikované Môžu byť prístupné iba cez dve nedeliteľné (atomické) operácie

wait (S) {

while S <= 0

; // no-op

S--;

} signal (S) {

S++;

}

6.17 ©2009Operačné systémy

Semafor ako všeobecný synchronizačný prostriedok

Počítací (Counting) semafor – jeho integer hodnota môže mať neobmedzený rozsah

Binárny (Binary) semafor – integer hodnota môže mať rozsah iba medzi 0 a 1; môže byť jednoduchší z hľadiska implementácie

Semafor je tiež známy ako mutex locks

Je možné implementovať počítací semafor S ako binárny semafor

Poskytuje (reprezentuje) „mutual exclusion“ – vzájomné vylučovanie implementované na báze semaforov

Semaphore mutex; // initialized to 1

do {

wait (mutex);

// Critical Section

signal (mutex);

// remainder section

} while (TRUE);

6.18 ©2009Operačné systémy

Implementácia semaforu

Musí garantovať že žiadne dva 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ód sú umiestnené v kritickej sekcii.

Mohol by mať teraz aktívne čakanie v implementácii kritickej sekcie

Avšak implementačný kód je krátky

Malé aktívne čakanie ak kritická sekcia je zriedkavo zamestnaná

Poznamenajme, že aplikácie môžu spotrebovať viac času v kritických sekciách a preto toto nie je dobré riešenie.

6.19 ©2009Operačné systémy

Implementácia semaforu bez aktívneho čakania

Ku každému semaforu je pričlenený front čakajúcich (procesov). Každý vstup vo fronte čakajúcich obsahuje dve dátové položky:

hodnota (typu integer)

ukazovateľ (pointer) na ďalší záznam v zozname

Dve operácie:

block (blokovať) – premiestni proces vyvolajúci operáciu do vhodného frontu čakajúcich.

wakeup (zobudiť) – premiestni jeden z procesov vo fronte čakajúcich do frontu pripravených (procesov).

6.20 ©2009Operačné systémy

Implementácia semaforu bez aktívneho čakania (Pokrač.)

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);

}

}

6.21 ©2009Operačné systémy

Uviaznutie a hladovanie

Deadlock (uviaznutie)– implementovanie semaforu s frontom čakajúcich môže vyústiť do situácie, kedy dva alebo viac procesov čakajú natrvalo na udalosť, ktorá môže byť spôsobená iba jedným z čakajúcich procesov. V prípade, že takýto stav nastane, hovoríme že procesy uviazli. Táto udalosť odpovedá vykonaniu operácie signal.

Uvažujme systém s dvoma procesmi P0 , P1 Oba procesy majú prístup k dvom semaforom S a Q nastaveným na hodnotu 1:

P0 P1

wait (S); wait (Q);

wait (Q); wait (S);

. .

signal (S); signal (Q);

signal (Q); signal (S);

Predpokladajme, že P0 ,P1 vykonajú po sebe wait(Q). Keď P0 vykoná wait(Q), musí čakať, až kým P1 vykoná signal(Q). Podobne, keď P1 vykoná wait(S) musí čakať, pokiaľ P0 vykoná signal(S). Preto operácie signal nemôžu byť vykonané, procesy P0 ,P1 sú uviaznuté.

6.22 ©2009Operačné systémy

Uviaznutie a hladovanie

Množina procesov sa nachádza v stave uviaznutia, ak každý proces v množine čaká na udalosť, ktorá môže byť spôsobená len nejakým procesom z danej množiny.

Udalosti, s ktorými sa predovšetkým stretávame a riešime ich, sú získanie a uvoľnenie zdrojov.

Starvation (hladovanie) – nekonečné blokovanie. Ide o stav, kedy proces čaká natrvalo (nekonečne) Proces nikdy nemôže byť odstránený zo semaforového radu, v ktorom je pozastavený.

Inverzia priority (Priority Inversion) - Problém plánovania, kedy proces nižšej priority drží zámok vyžadovaný procesom vyššej priority.

6.23 ©2009Operačné systémy

Klasické problémy synchronizácie

Problém ohraničeného zásobníka (Bounded-Buffer Problem)

Problém čitateľov a pisateľov (Readers and Writers Problem)

Problém obedujúcich filozofov (Dining-Philosophers Problem)

6.24 ©2009Operačné systémy

Problém ohraničeného zásobníka

N zásobníkov, každý je schopný držať jednu položku

Semafor mutex je inicializovaný na hodnotu 1

Semafor full je inicializovaný na hodnotu 0

Semafor empty je inicializovaný na hodnotu N.

6.25 ©2009Operačné systémy

Problém ohraničeného zásobníka (Pokrač.)

Štruktúra procesu „producent“

do {

// produce an item in nextp

wait (empty);

wait (mutex);

// add the item to the buffer

signal (mutex);

signal (full);

} while (TRUE);

6.26 ©2009Operačné systémy

Problém ohraničeného zásobníka (Pokrač.)

Štruktúra procesu „konzument“

do {

wait (full);

wait (mutex);

// remove an item from buffer to nextc

signal (mutex);

signal (empty);

// consume the item in nextc

} while (TRUE);

6.27 ©2009Operačné systémy

Problém čitatelia - pisatelia

Dátový objekt (typu súbor alebo záznam) je zdieľaný viacerými konkurenčnými procesmi

Čitatelia – iba čítajú z dátovej množiny, nevykonávajú akékoľvek „updates“ (procesy ktoré sa zaujímajú iba o čítanie)

Pisatelia – môžu aj čítať aj písať

Problém – dovoliť viacnásobným čítateľom čítať v tom istom čase. Len jeden môže mať prístup k zdieľaným dátam v tom istom čase.

Zdieľané dáta

Dátová množina (Data set)

Semafor mutex inicializovaný na hodnotu 1

Semafor wrt inicializovaný na hodnotu 1

Integer readcount inicializovaný na hodnotu 0

6.28 ©2009Operačné systémy

Problém čitatelia - pisatelia (Pokrač.) Štruktúra procesu „pisateľ“

do {

wait (wrt) ;

// writing is performed

signal (wrt) ;

} while (TRUE);

6.29 ©2009Operačné systémy

Štruktúra procesu Pisateľ - Čitateľ (Pokrač.)

Štruktúra procesu „čitateľ“

do { wait (mutex) ; readcount ++ ; if (readcount == 1)

wait (wrt) ; signal (mutex) // reading is performed

wait (mutex) ; readcount - - ; if (readcount == 0)

signal (wrt) ; signal (mutex) ; } while (TRUE);

6.30 ©2009Operačné systémy

Problém obedujúcich filozofov

Zdieľané dáta

Miska ryže (dátová množina) Semafor chopstick [5] inicializovaný na hodnote 1

6.31 ©2009Operačné systémy

Problém obedujúcich filozofov (Pokrač.)

Štruktúra filozofa i:

do {

wait ( chopstick[i] );

wait ( chopStick[ (i + 1) % 5] );

// eat

signal ( chopstick[i] );

signal (chopstick[ (i + 1) % 5] );

// think

} while (TRUE);

6.32 ©2009Operačné systémy

Problémy so semaformi

Nesprávne použitie semaforových operácií (výmena operácií, nahradenie operácií navzájom a pod.):

signal (mutex) …. wait (mutex)

wait (mutex) … wait (mutex)

Vynechať (opomenúť) wait (mutex) alebo signal (mutex) (alebo oba). V tomto prípade je porušené vzájomné vylúčenie alebo nastane uviaznutie.

6.33 ©2009Operačné systémy

Monitory

Abstrakcia vysokej úrovne, ktorá poskytuje vhodný a efektívny mechanizmus pre synchronizáciu procesov

Len jeden proces smie byť v danom čase aktívny vo vnútri monitora.

monitor monitor-name

{

// shared variable declarations

procedure P1 (…) { …. }

procedure Pn (…) {……}

Initialization code ( ….) { … }

}

}

6.34 ©2009Operačné systémy

Schematický pohľad na Monitor

6.35 ©2009Operačné systémy

Premenné typu Condition

condition x, y;

Programátor, ktorý potrebuje vytvoriť vlastnú (na mieru šitú) synchronizačnú schému, môže definovať jednu alebo viac premenných typu condition. Jediné operácie, ktoré môžu byť vyvolané na condition premenných sú wait a signal.

x.wait () – táto operácia znamená, že proces vyvolávajúci túto operáciu je suspendovaný, až kým iný proces vyvolá doleuvedenú operáciu x.signal ()

x.signal () – táto operácia obnoví presne jeden pozastavený proces- Ak žiadny proces nie je pozastavený, tak operácia signal nemá žiadny účinok, to znamená že stav x je ako keby operácia nebola nikdy vykonaná.

6.36 ©2009Operačné systémy

Monitor s premennými typu Condition

6.37 ©2009Operačné systémy

Riešenie k problému obedujúcich filozofov

monitor DP

{

enum { THINKING; HUNGRY, EATING) state [5] ;

condition self [5];

void pickup (int i) {

state[i] = HUNGRY;

test(i);

if (state[i] != EATING) self [i].wait;

}

void putdown (int i) {

state[i] = THINKING;

// test left and right neighbors

test((i + 4) % 5);

test((i + 1) % 5);

}

6.38 ©2009Operačné systémy

Riešenie k problému obedujúcich filozofov (Pokrač.)

void test (int i) {

if ( (state[(i + 4) % 5] != EATING) &&

(state[i] == HUNGRY) &&

(state[(i + 1) % 5] != EATING) ) {

state[i] = EATING ;

self[i].signal () ;

}

}

initialization_code() {

for (int i = 0; i < 5; i++)

state[i] = THINKING;

}

}

6.39 ©2009Operačné systémy

Riešenie k problému obedujúcich filozofov (pokrač.)

Každý filozof I invokuje operácie pickup()

a putdown() v nasledujúcej postupnosti:

DiningPhilosophters.pickup (i);

EAT

DiningPhilosophers.putdown (i);

6.40 ©2009Operačné systémy

Implementácia Monitoru použitím Semaforov

Premenné semaphore mutex; // (initially = 1)semaphore next; // (initially = 0)int next-count = 0;

Každá procedúra F bude nahradená

wait(mutex); …

body of F;

…if (next_count > 0)

signal(next)else

signal(mutex);

Vzájomné vylúčenie v rámci monitoru je zabezpečené.

6.41 ©2009Operačné systémy

Implementácia Monitoru

Pre každú premennú x typu condition máme:

semaphore x_sem; // (initially = 0)int x-count = 0;

Operácia x.wait môže byť implementovaná nasledovne:

x-count++;if (next_count > 0)

signal(next);else

signal(mutex);wait(x_sem);x-count--;

6.42 ©2009Operačné systémy

Implementácia Monitoru

Operácia x.signal môže byť implementovaná:

if (x-count > 0) {next_count++;signal(x_sem);wait(next);next_count--;

}

6.43 ©2009Operačné systémy

Monitor pre pridelenie jediného zdroja

monitor ResourceAllocator {

boolean busy; condition x; void acquire(int time) {

if (busy) x.wait(time);

busy = TRUE; } void release() {

busy = FALSE; x.signal();

} initialization code() {

busy = FALSE; }

}

6.44 ©2009Operačné systémy

Príklady Synchronizácie

Solaris

Windows XP

Linux

Pthreads

6.45 ©2009Operačné systémy

Synchronizácia Solaris-u

Implementuje rozmanité zámky pre podporu multitasking-u, multithreading-u (zahrňajúc vlákna reálneho času), a multiprocessing

Používa adaptive mutexes kvôli účinnosti pri ochrane dát pre kratšie segmenty kódu

Používa premenné typu condition a čitateľ-pisateľ zámky ktoré sú relatívne náročné na implementáciu, preto sa používajú iba na dlhšie segmenty kódu (ktoré potrebujú prístup k dátam)

Používa turnikety Turniket je frontová štruktúra obsahujúca vlákna blokované na zámku. Solaris 2 používa turnikety na poradie frontu vlákien čakajúcich na získanie buď adaptívneho mutexu alebo čitateľ-pisateľ zámku.

top related