Wybrane zadania z programowania wspóªbie»nego Cz ± I Semafory Drukarki W biurowcu Semso dziaªa N rm. Znajduje si tam równie» 0 < K N drukarek, z których korzystaj wspólnie pracownicy rm. Zasady korzystania z drukarek s nast puj ce. Pracownicy ró»nych rm nigdy nie korzystaj z tej samej drukarki jednocze±nie (przyjmujemy,»e jest dana procedura drukuj(nr_drukarki:1..k), której wywoªanie oznacza korzystanie z drukarki: wysªanie dokumentu, oczekiwanie na wydrukowanie i odbiór dokumentu z drukarki). Pracownik danej rmy nie mo»e rozpocz drukowania nie maj c pewno±ci,»e drukarka na któr chce wysªa swój dokument nie jest wykorzystywana przez pracowników innych rm. Pracownicy tej samej rmy w danej chwili mog korzysta tylko z jednej drukarki. Je»eli jest wiele wolnych drukarek, to pracownik, którego rma nie drukuje, mo»e wybra dowoln z nich (nie dbamy o równomierne wykorzystanie drukarek). Rozwi zanie ochrona: binary semaphore := 1; reszta: array [1..N] of binary semaphore := (0,...,0); pierwsi: binary semaphore := 0; ilu_czeka: array [1..N] of integer := (0,...,0); ile_firm_czeka: integer := 0; przydzial: array [1..N] of integer := (0,...,0); ilu_drukuje: array [1..K] of integer := (0,...,0); ile_wolnych: integer := K; process Pracownik(nr:1..N) nr_drukarki; repeat wlasne_sprawy; P(ochrona); if (przydzial[nr] = 0 and ile_wolnych = 0) or ile_firm_czeka > 0 then inc(ilu_czeka); if ilu_czeka[nr] > 1 then V(ochrona); P(reszta[nr]); else inc(ile_firm_czeka); V(ochrona); P(pierwsi); dec(ile_firm_czeka); 1
dec(ilu_czeka); if przydzial[nr] = 0 then nr_drukarki:=1; while ilu_drukuje[nr_drukarki] do inc(nr_drukarki); przydzial[nr]:=nr_drukarki; dec(ile_wolnych); nr_drukarki:=przydzial[nr]; inc(ilu_drukuje(nr_drukarki); if ilu_czeka[nr]>0 then V(reszta[nr]) else if ile_wolnych > 0 and ile_firm_czeka > 0 then V(pierwsi); else V(ochrona); drukuj(nr_drukarki); P(ochrona); dec(ilu_drukuje(nr_drukarki); if ilu_drukuje(nr_drukarki)=0 then inc(ile_wolnych); przydzial[nr]:=0; if ile_firm_czeka > 0 then V(pierwsi) else V(ochrona); else V(ochrona); forever 2
Biblioteka mikrolmów W bibliotece mikrolmów w Semlandii znajduje si N mikrolmów, ponumerowanych od 0 do N 1. W bibliotece znajduj si dwie czytelnie z K stanowiskami do odczytu mikrolmów. Klient, który chce skorzysta z czytelni udaje si najpierw do informacji. Po podaniu numeru mikrolmu, który chce przejrze, zostaje skierowany do której± czytelni. Klient przechodzi do niej i je±li jest w niej wolne stanowisko i mikrolm jest dost pny, to klient mo»e rozpocz jego przegl danie. Je±li kto± inny wªa±nie korzysta z tego mikrolmu lub w czytelni nie ma wolnych stanowisk, to klient musi poczeka. W obu czytelniach jest wystarczaj co du»o miejsca, aby pomie±ci wszystkich oczekuj cych. Klient musi uda si do czytelni, do której zostaª skierowany i nie wolno mu przechodzi do drugiej czytelni. Po zako«czeniu korzystania z mikrolmu, klient zwalnia zasoby (mikrolm i stanowisko) i opuszcza bibliotek. Schemat dziaªania klienta mo»na zatem opisa nast puj co: process Klient; czytelnia: 1..2; mikrofilm: 0..N-1; while true do wlasne_sprawy; czytelnia := Informacja_Dokad (mikrofilm); PRZEJDZ_DO_CZYTELNI (czytelnia); Czekaj_Na_Zasoby (czytelnia, mikrofilm); CZYTAJ; Zwolnij_Zasoby (czytelnia, mikrofilm) Poniewa» w informacji jest maªo miejsca, klienci nie mog tam oczekiwa na zasoby, zatem funkcja Informacja_Dokad jest nieblokuj ca, z wyj tkiem by mo»e krótkiego oczekiwania na obsªu»enie. Zaimplementuj funkcj Informacja_Dokad i procedury Czekaj_Na_Zasoby i Zwolnij_Zasoby za pomoc semaforów. Zadbaj o jak najlepsze wykorzystanie czytelni, ale pami taj o tym, aby nie doszªo do zagªodzenia»adnego procesu. Rozwi zanie mutex: binary semaphore = 1; czekaj: array [0..N-1] of bin sem = (1,..., 1); iluw: array [1..2, 0..N-1] of integer = ((0, 0), N * 0); {iluw[c, f] --- ilu amatorow filmu f znajduje sie w czytelni c} ilezas: array[1..2] of integer = (0, 0); {ilezas --- liczba zaangazowanych mikrofilmow w poszczegolnych czytelniach (tj. takich, z ktorych sie korzysta lub na ktore sie czeka} czytelnia: array [ 1..2] of semaphore = (K, K); 3
function Informacja_Dokad (mikro: 0..N-1): 1..2; czyt : 1..2; PB (mutex); if iluw[1, mikro] > 0 then czyt := 1 else if iluw[2, mikro] > 0 then czyt := 2 else if ilezas[1] < ilezas[2] then inc (ilezas[1]); czyt := 1 else inc (ilezas[2]); czyt := 2 inc (iluw[czyt, mikro]); Informacja_Dokad := czyt; VB (mutex) procedure Czekaj_Na_Zasoby (czyt: 1..2; mikro: 0..N-1); PB (czekaj[mikro]); P (czytelnia[czyt]); procedure Zwolnij_Zasoby (czyt: 1..2; mikro: 0..N-1); j: 0..N-1; PB (mutex); dec (iluw[czyt, mikro]); if iluw[czyt, mikro] = 0 then dec (ilezas[czyt]); VB (czekaj[mikro]); V (czytelnia[czyt]) 4
Poziomy umiej tno±ci Firma Semso zatrudnia pewn liczb pracowników. Ka»dy pracownik ma przydzielony identy- kator (typu identprac) oraz poziom umiej tno±ci (typu integer). Firma obsªuguje klientów, z których ka»dy ma przydzielony identykator (typu identklienta). Ka»dy klient mo»e by obsªugiwany przez grup pracowników, których suma poziomów umiej tno±ci wynosi co najmniej M. Zakªadamy,»e poziom umiej tno±ci ka»dego pracownika jest mniejszy od M. Klient w p tli niesko«czonej zajmuje si najpierw wªasnymi sprawami, a nast pnie zgªasza si do rmy Semso z pro±b o obsªug. Klient przekazuje przydzielonym mu pracownikom swój identykator oraz otrzymuje zbiorczy identykator (typu identgrupy) caªej grupy obsªuguj cych go pracowników. Pracownicy w niesko«czonej p tli obsªuguj klientów swojej rmy. Ka»dy pracownik musi zna identykator obsªugiwanego klienta. Dane s nast puj ce procedury: procedure init(id : identprac; idg : identgrupy) inicjacja zbiorczego identy- katora grupy pracowników idg na identykator jednego pracownika id, procedure dodaj( idg : identgrupy; id : identprac) dodanie do zbiorczego identykatora idg identykatora id kolejnego pracownika z tej samej grupy, praca(id : identklienta) wywoªywana w procesie pracownika (obsªuga przez tego pracownika klienta o identykatorze id), obsªuga(zid : identgrupy) wywoªywana w procesie klienta (obsªuga tego klienta przez grup pracowników o zbiorczym identykatorze zid). Zapisz przy u»yciu semaforów tre± procesów: process Klient (id : identklienta), process Pracownik (id : identprac; pozum : integer). Rozwi zanie Ochrona : binary semaphore = 1; Pracownicy : binary semaphore = 0; sumapoz : integer = 0; Pierwszy : binary semaphore = 0; idklienta : identklienta; Klienci : binary semaphore = 0; ileklient : integer = 0; idgrupy : identgrupy; pozgrupy : integer = 0; {czekaja wszyscy pracownicy} {suma poziomow czekajacych prac.} {pierwszy klient} {id pierwszego klienta} {pozostali klienci} {liczba czekajacych klientow} {zbiorcze id grupy pracownikow} {suma poziomow tworzonej grupy} process Pracownik (id : identprac; poz : integer); mojklient : identklienta; while true do P(Ochrona); sumapoz:= sumapoz + poz; if (ileklient > 0) and (sumapoz >= M) then {rozpoczynamy prace} 5
mojklient:= idklienta; init(id, idgrupy); {pierwszy pracownik tworzy grupe} pozgrupy:= poz; {suma poziomow umiejetnosci grupy} V(Pracownicy) {zbudzenie nastepnego pracownika} else {czekamy: brak klienta lub pracownikow} V(Ochrona); P(Pracownicy); mojklient:= idklienta; {po zbudzeniu: pobiera id klienta} if pozgrupy = 0 then init(id, idgrupy) else dodaj(idgrupy, id); {aktualizacja zbiorczego id} pozgrupy:= pozgrupy + poz; if pozgrupy < M then {grupa jeszcze niepelna} V(Pracownicy) else {pracownicy w komplecie} sumapoz:= sumapoz - pozgrupy; {ostatni robi porzadki} pozgrupy:= 0; V(Pierwszy) {budzi klienta} praca(mojklient) process Klient (id : identklienta); idprac : identgrupy; while true do wlasnesprawy; P(Ochrona); if sumapoz >= M then {sa pracownicy} idklienta:= id; {przekazanie im swego id} V(Pracownicy); {i zbudzenie pierwszego pracownika} P(Pierwszy); {czekanie na zbiorczy id grupy} idprac:= idgrupy; {dziedziczenie sekcji} V(Ochrona) else {nie ma pracownikow, czekamy} ileklient:= iluklient + 1; if ileklient = 1 then {pierwszy klient} idklienta:= id {przekazuje swoj id} else {nastepny klient} V(Ochrona); P(Klienci); {czeka na tym semaforze} idklienta:= id {staje sie pierwszym klientem} V(Ochrona) {klient zwalnia sekcje} 6
P(Pierwszy); idprac:= idgrupy; ileklient:= ileklient - 1; if ileklient > 0 then V(Klienci) else V(Ochrona) obsluga(idprac); {i czeka jako pierwszy} {pobranie zbiorczego id} {kolejny klient staje sie pierwszym} {zwolnienie sekcji po dziedziczeniu} 7
Górskie wycieczki (zadanie z kolokwium SO w 2008) Górski punkt wycieczkowy organizuje wycieczki w góry o T 1 stopniach trudno±ci. Wycieczki prowadz przewodnicy. Ka»dy przewodnik ma uprawnienia wyra»one liczb od 1 do T, przy czym przewodnik o uprawnieniach t mo»e kierowa wycieczk o trudno±ci nie wi kszej ni» t. Dla ka»dego 1 t T jest co najmniej jeden przewodnik o uprawnieniach t. Liczno± grupy zale»y od stopnia trudno±ci wycieczki: na wycieczk o trudno±ci t mo»e wyj± grupa od GM IN(t) do GM AX(t) (wª cznie) uczestników i dokªadnie jeden przewodnik. Wiadomo przy tym,»e 1 t T 1 GMIN(t) GMAX(t). Uczestnik cyklicznie wykonuje WŠASNE_SPRAWY, losuje poziom trudno±ci kolejnej wycieczki (funkcja LOSUJ(T)) i (by mo»e po oczekiwaniu na grup i/lub przewodnika) wraz z grup i przewodnikiem wybiera si na wycieczk (procedura WYCIECZKA(nr_przewodnika: integer)). Przewodnik cyklicznie wykonuje WŠASNE_SPRAWY, zgªasza si do pracy, zabiera na wycieczk pewn skompletowan grup (o liczno±ci GM IN(t)), wybieraj c przy tym wycieczk o najwi kszej trudno±ci, któr jest w stanie poprowadzi. Je±li»adna grupa nie jest gotowa lub przewodnik nie ma wystarczaj cych uprawnie«, to przewodnik musi poczeka. Gdy zbieraj ca si grupa osi gnie liczno± GMIN(t) i czeka pewien przewodnik o uprawnieniach t, to jest budzony przewodnik o najni»szych dostatecznych uprawnieniach spo±ród oczekuj cych przewodników. Zabiera on grup na wycieczk (procedura WYCIECZKA). Po zako«czeniu wycieczki ka»dy uczestnik (bez synchronizacji z innymi) rozpoczyna ponownie wykonanie wªasnych spraw. Zapisz tre± procesów Przewodnik(nr: integer; upr: 1..T) i Uczestnik, u»ywaj c do synchronizacji semaforów ogólnych i/lub binarnych. Parametr nr jest unikatowym numerem przewodnika, a upr okre±la jego uprawnienia. Rozwi zanie ochrona: binary semaphore := 1; przewodnicy: array [1..T] of binary semaphore := (0,...); grupy: array [1..T] of binary semaphore := (0,...); ilu_przewodników: array [1..T] of integer := (0,...); ilu_czeka: array [1..T] of integer := (0,...); obudzonych, teraz_rusza: integer := 0; function znajd¹_grup (upr: 1..T): 0..T; i: integer; for i := upr downto 1 do if ilu_czeka[i] > GMIN(i) then return i; return 0; function znajd¹_przewodnika(upr: 1..T): 0..T; i: integer; 8
for i := upr to T do if ilu_przewodników[i] > 0 then return i; return 0; process Przewodnik(nr: 1..MAXINT; upr: 1..T); gr: integer; repeat WŠASNE_SPRAWY; P(ochrona); gr := znajd¹_grup (upr); if gr = 0 /* nie ma zebranej grupy */ then inc(ilu_przewodników[upr]); V(ochrona); P(przewodnicy[upr]); dec(ilu_przewodników[upr]); gr := znajd¹_grup (upr); /* jest grupa, by mo»e kto± nas obudziª * i wtedy ponownie szukali±my grupy */ teraz_rusza := nr; obudzonych := 0; /* na pewno kto± czeka, zaczynamy budzenie uczestników */ V(grupy[gr]); WYCIECZKA(); until false; process Uczestnik; gr, poz_prz: integer; mój_przew: integer; repeat WŠASNE_SPRAWY; gr := LOSUJ(T); P(ochrona); inc(ilu_czeka[gr]); if ilu_czeka[gr] >= GMIN(gr) and znajd¹_przewodnika(gr)!= 0 then /* budzimy przewodnika */ V(przewodnicy[znajd¹_przewodnika(gr)]; else /* czekamy na przewodnika lub reszt */ V(ochrona); /* zawsze zasypia, przewodnik obudzi 1-szego uczestnika */ 9
P(grupy[gr]); dec(ilu_czeka[gr]); mój_przew := teraz_rusza; inc(obudzonych); if obudzonych < GMAX(gr) and ilu_czeka[gr] > 0 then V(grupy[gr]) else V(ochrona); WYCIECZKA(mój_przew); until false; 10
Czytelnicy i pisarze z zamian ról Cz ± II Monitory W pewnym systemie dziaªaj procesy, z których ka»dy cyklicznie zaªatwia wªasne_sprawy, po czym wchodzi do sekcji_krytycznej. Dost p do sekcji krytycznej mo»e by wyª czny albo dzielony. Proces» daj cy wyª cznego dost pu do sekcji krytycznej przebywa w niej jako jedyny. Proces» - daj cy dost pu dzielonego mo»e korzysta z sekcji krytycznej w tym samym czasie, co inne procesy» daj ce dost pu dzielonego. Wiadomo ponadto,»e ka»dy proces przebywaj cy w sekcji krytycznej co najwy»ej raz za» da zmiany sposobu korzystania z sekcji. Procesy» daj ce zmiany sposobu dost pu z dzielonego na wyª czny zostaj wstrzymane do momentu, w którym b d mogªy korzysta z sekcji na zasadzie wyª czno±ci. Maj one przy tym pierwsze«stwo przed nowymi procesami. Zaprogramuj monitor synchronizuj cy procesy zgodnie z powy»szym opisem. Monitor ma udost pnia cztery bezparametrowe procedury: wyª czny, dzielony, zmiana i koniec. Rozwi zanie monitor Serwer; WYLACZNY, ZMIANA, DZIELONY: condition; wylacz, dziel: integer; export procedure dzielony; if not empty(wyš CZNY) or not empty(zmiana) or wyª cz>0 then wait(dzielony); dziel := dziel + 1; signal(dzielony) /* kaskada */ {dzielony}; export procedure wyª czny; if wyª cz+dziel>0 then wait(wyšaczny); wyª cz := 1 {wyª czny}; export procedure koniec; if wyª cz>0 then wyª cz := 0; if not empty(zmiana) then signal(zmiana) else if empty(dzielony) then signal(wyš CZNY) else signal(dzielony); /* pierwszy czytelnik */ else dziel := dziel -1; if dziel = 0 then 11
if not empty(zmiana) then signal(zmiana) else if empty(wyš CZNY) then signal(dzielony) else signal(wyš CZNY); {koniec}; export procedure zmiana; if wyª cz>0 then /* byªem sam */ wyª cz := 0; dziel := 1; signal(dzielony) else /* byªo nas wielu */ if dziel = 1 then dziel := 0; wyª cz := 1 else dziel := dziel -1; wait(zmiana); wyª cz := 1 wylacz := 0; dziel := 0. 12
Grupy i zasoby W systemie N grup procesów (liczno± grup nie jest znana) korzysta z K zasobów ponumerowanych od 1 do K. Ka»dy proces dziaªa wedªug schematu: process P(grupa: 1..N) k: integer; while true do wªasne_sprawy; SERWER.chc _korzysta (grupa, k); korzystam(k); SERWER.sko«czyªem(grupa,k); Zasady korzystania z zasobów s nast puj ce: Dwie grupy nie korzystaj jednocze±nie z tego samego zasobu. Procesy z jednej grupy korzystaj w danej chwili z co najwy»ej jednego zasobu. Je»eli jaki± zasób jest wolny, to»aden proces, który chce korzysta z zasobu nie powinien czeka. Napisz monitor SERWER zarz dzaj cy dost pem do zasobów w taki sposób, aby powy»sze warunki warunki byªy speªnione i»aden proces nie zostaª zagªodzony. Rozwi zanie monitor SERWER; pierwsi: condition; reszta: array [1..N] of condition ile_czeka: array [1..N] of integer; ile_korzysta: array [1..K] of integer; przydziaª: array [1..N] of integer; ile_wolnych: integer; export procedure chc _korzysta (grupa: integer, k: integer); if (ile_wolnych=0 and przydzial[i]=0) or not empty(pierwsi) then inc(ile_czeka[i]); if (ile_czeka[i]=1) then wait(pierwsi); else wait(reszta[i]); dec(ile_czeka[i]); if przydzial[i] = 0 then 13
k:=1; while (ile_korzysta[k]>0) do inc(k); przydzial[i]:=k; dec(ile_wolnych); else k:=przydzial[i]; inc(ile_korzysta[k]); signal(reszta[i]); if (ile_wolnych > 0) then signal(pierwsi); { grupa mogªa doª czy do procesów, które pracowaªy wcze±niej i wci» mog by wolne zasoby } export procedure sko«czyªem(i,k: integer); dec(ile_korzysta[k]); if ile_korzysta[k]=0 then przydzial[i]:=0; inc(ile_wolnych); signal(pierwsi); ile_wolnych:=k; for i=1 to K do ile_korzysta[i]:=0; for i=1 to N do przydziaª[i]:=0; for i=1 to N do ile_czeka[i]:=0;. 14
Centrum Terapeutyczne Centrum Terapeutyczne dla Studentów po Egzaminie z SO zatrudnia pewn liczb terapeutów oraz dysponuje G > 0 gabinetami. Po zgªoszeniu si do centrum pacjent jest najpierw diagnozowany indywidualnie przez terapeut : czeka na terapeut i gabinet, którego numer musi pozna i wywoªuje predeniowan procedur Diagnoza, której wynikiem jest rodzaj zalecanej terapii. Nast pnie zgªasza si na terapi : czeka na terapeut (by mo»e innego) i gabinet oraz odbywa sesj terapeutyczn indywidualn albo grupow (predeniowana procedura Sesja). W terapii grupowej bierze zawsze udziaª P > 0 pacjentów, którzy tworz grup zgodnie z kolejno±ci zgªaszania si na terapi. Spotkania terapeutów z pacjentami odbywaj si zawsze w gabinetach zarówno podczas diagnozowania jak i sesji. Po ka»dym spotkaniu z terapeut (zarówno diagnostycznym jak i terapeutycznym) pacjent opuszcza gabinet, przy czym pacjenci ko«cz terapi grupow pojedynczo i niezale»nie od siebie. Terapeuta zgªasza si najpierw do pracy, gdzie czeka na pacjentów i gabinet. Nast pnie udaje si do wskazanego gabinetu, gdzie spotyka si z pacjentem lub pacjentami (predeniowana procedura Praca). Gdy uznaje,»e spotkanie dobiegªo ko«ca (tj. zako«czyªa si procedura Praca), czeka a» ostatni (by mo»e jedyny przy diagnozowaniu lub terapii indywidualnej) pacjent opu±ci gabinet, po czym zwalnia gabinet. Napisz monitor synchronizuj cy prac centrum. Pacjenci i terapeuci dziaªaj w nast puj cy sposób: process Pacjent; gab1, gab2: integer rodzaj: (ind, grup); repeat CENTRUM.ZglaszamSie(gab1); rodzaj:= Diagnoza(gab1); CENTRUM.Koniec(gab1); Odpoczynek; CENTRUM.Terapia(gab2, rodzaj); Sesja(gab2); CENTRUM.Skonczylem (gab2) until false; process Terapeuta; gab: integer; repeat CENTRUM.Zglaszamsiedopracy(gab); Praca (gab); CENTRUM.Zwalniam(gab); Odpoczynek until false; Rozwi zanie monitor CENTRUM; ilu: integer; {zlicza pacjentow zbierajacych sie na terapie grupowa} gabinet: integer; {do przekazywania numeru gabinetu} wolneg: integer; {liczba wolnych gabinetow} 15
terapeuci, diagnoza, terapia: condition; {do wieszania terapeutów, diagnozowanych, czekajacych na terapie} komplet: condition; {tu czekamy na kompletna grupe} iluw: array [1..G] of integer; {ilu pacjentow w gabinecie} koniec: array [1..G] of condition; {tu czekaja terapeuci na wyjscie pacjentow} {Zakªadamy,»e terapeuta bedzie zabieraª pacjenta, chyba»e przychodzi pacjent a terapeuci czekaja - porównaj z zadaniem o urz dnikach z wicze«} export procedure ZglaszamSie ( gab: integer); if empty (terapeuci) or (wolneg = 0) then wait (diagnoza) {obudzi mnie terapeuta} else signal (terapeuci); gab := gabinet; iluw [gab] := 1; wolneg := wolneg - 1; export procedure Terapia ( gab: integer; r: (ind, grup)); if r = grup then ilu := (ilu + 1) mod P; if (ilu <> 0) and (r = grup) then wait (komplet) else {indywidualny lub ostatni z grupy} if empty (terapeuci) or (wolneg = 0) then wait (terapia) else signal (terapeuci); wolnyg := wolnyg - 1; if r = grup then for i := 1 to P-1 do signal(komplet); gab := gabinet; iluw[gab] := iluw[gab]+1; 16
export procedure Koniec/Skonczylem (gab: integer); iluw[gab] := iluw[gab]-1; if iluw[gab] = 0 then signal (koniec[gab]) export procedure ZglaszamSiedopracy ( gab: integer); if wolneg = 0 or empty (diagnoza) or empty (terapia) then wait (terapeuta); gab := 1; while iluw[gab] <> 0 do gab := gab+1; gabinet := gab; if not empty (terapia) then {najpierw terapia, zeby nie zaglodzic} signal (terapia) else signal (diagnoza); export procedure Zwalniam (gab: integer); if iluw[gab] > 0 then wait (koniec[gab]); wolneg := wolneg - 1; if not empty (terapeuci) and (not empty (terapia) or not empty (diagnoza)) then signal (terapeuci) { budzimy terapeute, on obudzi pacjenta, a pacjent ewentualnie innych pacjentow do grupy } wolneg := 0; ilu := 0; for i to G do iluw[i] := 0;. 17
Dyskoteka (zadanie z kolokwium SO 2008) W pewnej dyskotece bawi sie procesy. Jednocze±nie na parkiecie mo»e przebywa co najwy»ej K > 1 procesów. Ka»dy proces przychodz c na dyskotek czeka na dowolny proces odmiennej pªci, oba procesy czekaj na wolne miejsca na parkiecie, po czym razem id ta«czy. Ka»dy z nich ko«czy taniec niezale»nie od drugiego. W dyskotece pracuje te» DJ, który dba o to, aby muzyka graªa wtedy i tylko wtedy, gdy parkiet jest niepusty (to oznacza,»e muzyka mo»e nigdy nie zamilkn ). Napisz monitor DYSKOTEKA. Tre±ci procesów s nast puj ce: process Proces(nr: integer;plec: 0..1); partner: integer; repeat DYSKOTEKA.CzekajNaPartneraIMiejsce (nr, plec, partner); tanczz(partner); DYSKOTEKA.Koncz; until false process DJ; repeat DYSKOTEKA.CzekajNaNiepusty; wlaczmuzyke; DYSKOTEKA.CzekajNaPusty; wylaczmuzyke; until false Rozwi zanie monitor DYSKOTEKA; wolne, id, int; czekamy: bool; single: array[0..1] of condition; parkiet, dj: condition; export procedure CzekajNaPartneraIMiejsce(i, p:int, j:int) if empty(single[1-p]) then wait(single[p]); j := id; id := i; czekamy := false; if wolne < 2 then czekamy := true; wait(parkiet); else if wolne = K then signal(dj); else id := i; signal(single[1-p]); j := id; 18
if czekamy then wait(parkiet); dec(wolne); export procedure Koncz; inc(wolne); if wolne >= 2 then signal(parkiet); signal(parkiet); if wolne = K then signal(dj); export procedure CzekajNaPoczatek; if wolne = K then wait(dj); export procedure CzekajNaKoniec; if wolne < K then wait(dj); wolne := K;. 19