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.