W systemie działają dwa typy procesów: Klient i Pracownik. W systemie dostępny jest monitor Biuro. Klient umieszcza zadanie w monitorze Biuro. Pracownik przetwarza zadanie i zostawia rezultat tej pracy w monitorze Biuro. Klient odbiera rezultat. Procesy w nieskończonej pętli powtarzają te czynności.
monitor Biuro;
type
zadanie_t = ...;
rezultat_t = ...;
export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t);
export procedure przetwarzanie();
process Klient
var
zadanie: zadanie_t;
rezultat: rezultat_t;
begin
while (true) do
begin
zadanie = przygotowanie_zadania();
Biuro.zlecenie_przetwarzania(zadanie, rezultat);
przetwarzanie_rezultatu(rezultat);
end;
end;
process Pracownik
begin
while (true) do
begin
Biuro.przetwarzanie();
end;
end;
Zsynchronizuj działanie procesów, rozważ warianty:
Jeden klient i jeden pracownik
Przetwarzanie wewnątrz monitora
Przetwarzanie na zewnątrz monitora
export procedure pobieranie_zadania(out p_zadanie: zadanie_t);
export procedure umieszczanie_rezultatu(in p_rezultat: rezultat_t);
process Pracownik
begin
while (true) do
begin
Biuro.pobieranie_zadania(zadanie);
rezultat := praca(zadanie);
Biuro.umieszczanie_rezultatu(rezultat);
end;
end;
Wielu klientów i wielu pracowników.
monitor Biuro;
type
zadanie_t = ...;
rezultat_t = ...;
var
aktualne_zadanie: zadanie_t;
aktualny_rezultat: rezultat_t;
czeka_klient: condition;
czeka_pracownik: condition;
export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t)
begin
aktualne_zadanie := p_zadanie;
if (not empty(czeka_pracownik)) then
signal(czeka_pracownik);
else {: else jest konieczne - wait nie moze sie zawsze wykonywac :}
wait(czeka_klient);
p_rezultat = aktyalny_rezultat;
end;
export procedure przetwarzanie()
begin
if (empty(czeka_klient)) then
wait(czeka_pracownik);
p_rezultat = praca(p_zadanie);
if (not empty(czeka_klient))
signal(czeka_klient);
end;
Warto zwrócić uwagę na wykonywanie przez klienta albo instrukcji signal albo instrukcji wait. Gdyby instrukcja wait była wykonywana zawsze to program byłby niepoprawny. W tym przypadku załóżmy, że pracownik czeka na zmiennej czeka_pracownik, przychodzi klient, umieszcze zadanie, budzi pracownika, pracownik natychmiast przejmuje monitor wykonuje zadanie i ponieważ klient nie zdążył wykonać wait na czeka_klient to pracownik nie budzi klienta tylko wychodzi z monitora. Wtedy klient zostaje wznowiony i dopiero wtedy wykonuje wait na czeka_klient. Nastepnie przychodzi pracownik i zauważa że kolejka na zmiennej czeka_klient nie jest pusta więc uznaje, że na zmiennej aktualne_zadanie znajduje się aktualne zadanie (podczas gdy jest to stare, już przetworzone żadanie) i zaczyna je przetwarzać (drugi raz).
export procedure pobieranie_zadania(out p_zadanie: zadanie_t);
export procedure umieszczanie_rezultatu(in p_rezultat: rezultat_t);
process Pracownik
begin
while (true) do
begin
Biuro.pobieranie_zadania(zadanie);
rezultat := praca(zadanie);
Biuro.umieszczanie_rezultatu(rezultat);
end;
end;
monitor Biuro;
type
zadanie_t = ...;
rezultat_t = ...;
var
aktualne_zadanie: zadanie_t;
aktualny_rezultat: rezultat_t;
czeka_klient: condition;
czeka_pracownik: condition;
export procedure zlecenie_przetwarzania(in p_zadanie: zadanie_t, out p_rezultat: rezultat_t)
begin
aktualne_zadanie := p_zadanie;
if (not empty(czeka_pracownik)) then
signal(czeka_pracownik);
{: nie moze byc else - zawsze musimy czekac :}
wait(czeka_klient);
p_rezultat := aktyalny_rezultat;
end;
export procedure pobieranie_zadania(out p_zadanie: zadanie_t)
begin
if (empty(czeka_klient)) then
wait(czeka_pracownik);
p_zadanie := aktualne_zadanie;
end;
export procedure umieszczanie_rezultatu(in p_rezultat: rezultat_t)
begin
aktualny_rezultat := p_rezultat;
if (not empty(czeka_klient))
signal(czeka_klient);
end;
W tym przypadku klient musi wykonać wait na zmiennej czeka_klient zawsze. Gdyby klient postępował tak jak w przypadku przetwarzania wewnątrz monitora to program byłby niepoprawny. Załóżmy, że pracownik czeka na zmiennej czeka_pracownik, przychodzi klient, umieszcza zadanie, budzi pracownika, pracownik natychmiast przejmuje monitor, a następnie wychodzi z monitora. Wtedy zaczyna się wykonywać klient i pobiera rezultat ze zmiennej aktualny_rezultat, ale proces pracownik nie zdążył jeszcze umieścić tam rezultatu.