1 Programowanie wspóªbie»ne wiczenia 2 semafory cz. 1 Zadanie 1: Producent i konsument z buforem cyklicznym type porcja; void produkuj(porcja &p); void konsumuj(porcja p); porcja bufor[n]; / bufor cykliczny / semaphore wolne = N; / bufor jest pocz tkowo pusty / semaphore zajete = 0; process Producent() process Konsument() produkuj(p); P(wolne); bufor[k] = p; V(zajete); P(zajete); p = bufor[k]; V(wolne); konsumuj(p); Zadanie 2: Producent i wielu konsumentów z buforem cyklicznym type porcja; void produkuj(porcja &p); void konsumuj(porcja p); porcja bufor[n]; / bufor cykliczny / semaphore wolne = N; / bufor jest pocz tkowo pusty / semaphore zajete = 0; int gk = 0; binary semaphore ochrona = 1; process Producent() produkuj(p); P(wolne); bufor[k] = p; V(zajete); process Konsument[K] P(zajete); p = bufor[gk]; gk = (gk + 1) % N; V(wolne); konsumuj(p);
2 Zadanie 3: Semafor uogólniony Zdeniuj dwie operacje, nazwijmy je PG(n) oraz VG(n), oznaczaj ce odpowiednio opuszczenie oraz podniesienie semafora uogólnionego o n warto±ci. Zwró uwag na zachowanie wªasno±ci»ywotno±ci. Rozwi zanie bez dziedziczenia sekcji krytycznej binary semaphore ochrona = 1; / ochrona wspólnych zmiennych / binary semaphore reszta = 1; / semafor dla reszty czekaj cych / binary semaphore pierwszy = 0; / semafor dla pierwszego czekaj cego / int ile ; / aktualna warto± semafora / void PG(int n) / operacja P na semaforze uogólnionym / P(reszta); / zapewnia,»e co najwy»ej jeden proces czeka na semaforze pierwszy / ile = ile n; if ( ile < 0) / wstrzymanie / P(pierwszy); V(reszta); void VG(int n) / operacja V na semaforze uogólnionym / ile = ile + n; if (( ile >= 0) && (ile < n)) / kto± czeka i ju» si doczekaª / V(pierwszy); W przedstawionym rozwi zaniu zmienna reprezentuj ca warto± semafora przyjmuje czasowo warto±ci ujemne. Sposób dziaªania procesów (wstrzymywanie procesów) jest jednak caªkowicie prawidªowy. Rozwi zanie z dziedziczeniem sekcji krytycznej binary semaphore ochrona = 1; / ochrona wspólnych zmiennych / binary semaphore reszta = 1; / semafor dla reszty czekaj cych / binary semaphore pierwszy = 0; / semafor dla pierwszego czekaj cego / int ile ; / aktualna warto± semafora / int naileczeka ; / na ile czeka pierwszy czekaj cy / void PG(int n) / operacja P na semaforze uogólnionym / P(reszta); if ( ile < n) naileczeka = n; P(pierwszy); / dziedziczenie sekcji krytycznej /
3 naileczeka = 0; ile = ile n; V(reszta); void VG(int n) / operacja V na semaforze uogólnionym / ile = ile + n; if (( naileczeka > 0) && (ile > = naileczeka)) V(pierwszy); / przekazanie sekcji krytycznej / Zadanie 4: Czytelnicy i pisarze W systemie dziaªaj dwa typy procesów: czytelnicy i pisarze. Pisarze zapisuj, a czytelnicy odczytuj dane. Je±li pisarz pisze, to»aden inny proces nie czyta ani nie pisze. Jednocze±nie mo»e (i powinno) czyta wielu czytelników. Zanim napiszemy program, zastanówmy si, jaki jest ogólny schemat rozwi zywania tego typu zada«synchronizacyjnych. Mamy tutaj dwie grupy procesów, które musz w jaki± sposób zsynchronizowa korzystanie z czytelni tak b dziemy nazywa wykonanie operacji czytania przez czytelnika lub pisania przez pisarza. Nie znamy liczby czytelników ani pisarzy mo»e ich by dowolnie du»o. Podobnie w»aden sposób nie limitujemy liczby miejsc w czytelni. Projektuj c protokoªy wst pne odpowiadamy na pytanie Kiedy proces powinien poczeka?. Z kolei pisz c protokoªy ko«cowe podejmuje decyzj, któr grup procesów czekaj cych w protokoªach wst pnych, obudzi. Spróbujmy zatem opisa protokoªy wst pne i ko«cowe czytelnika i pisarza. Protokóª wst pny czytelnika: czytelnik czeka, je±li w czytelni jest pisarz. Protokóª wst pny pisarza: pisarz czeka je±li, w czytelni jest czytelnik lub pisarz. Protokóª ko«cowy czytelnika: je±li jest ostatnim wychodz cym, to budzi pisarza o ile jaki± czeka. Protokóª ko«cowy pisarza: je±li czekaj czytelnicy, to inicjuje budzenie wszystkich czekaj cych czytelników, w przeciwnym razie, je±li czekaj pisarze, to budzi jednego z nich. Zanim zaczniemy implementowa to rozwi zanie, odpowiedzmy na kilka pyta«. Czy takie rozwi zanie jest bezpieczne? Czy nie prowadzi do zagªodzenia czytelników? Czy nie prowadzi do zagªodzenia pisarzy? Przedstawione rozwi zanie mo»e zagªodzi pisarzy. Wska» scenariusz prowadz cy do takiej sytuacji. Poprawne rozwi zanie polega na zatrzymaniu czytelnika tak»e wtedy, gdy czeka pisarz. Protokóª wst pny czytelnika b dzie zatem nast puj cy: Protokóª wst pny czytelnika: czytelnik czeka, je±li w czytelni jest pisarz lub je±li czeka pisarz. Do realizacji powy»szego schematu nale»y u»y :
4 czterech liczników: dwóch dla czytelników oraz dwóch dla pisarzy, oznaczaj cych liczby procesów z danej grupy, które zgªosiªy ch skorzystania z czytelni oraz tych, które ju» korzystaj z czytelni; semafora binarnego do ochrony wspólnych zmiennych; dwóch semaforów, na których czekaj odpowiednio czytelnicy oraz pisarze. void czytam(); void pisz (); int iluczyta, ilupisze, czekaczyt, czekapis = (0, 0, 0, 0); binary semaphore ochrona = 1; semaphore Czytelnicy = 0; semaphore Pisarze = 0; process Czytelnik(int id) sekcja_lokalna; if ( ilupisze + czekapis > 0) czekaczyt++; P(Czytelnicy); / dziedziczenie sekcji krytycznej / czekaczyt ; ; iluczyta++; if (czekaczyt > 0) V(Czytelnicy); czytam(); iluczyta ; if (( iluczyta == 0) && (czekapis > 0)) V(Pisarze); process Pisarz(int id) sekcja_lokalna; if ( ilupisze + iluczyta > 0) czekapis++; P(Pisarze); / dziedziczenie sekcji krytycznej / czekapis ; ; ilupisze ++; pisz ();
5 ilupisze ; if (czekaczyt > 0) V(Czytelnicy); if (czekapis > 0) V(Pisarze); Zadanie dodatkowe Zapisz rozwi zanie problemu czytelników i pisarzy bez dziedziczenia sekcji krytycznej.