4. TEORETYCZNE MODELE PROCESÓW WSPÓŁBIEŻNYCH Teoretyczne modele uwzględniają wybrane cechy rzeczywistych procesów, stanowiąc kompromis pomiędzy łatwością

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

TRADYCYJNE METODY PLANOWANIA I ORGANIZACJI PROCESÓW PRODUKCYJNYCH
ANALIZA SIECIOWA PRZEDSIĘWZIĘĆ konstrukcja harmonogramu
Język C/C++ Funkcje.
Wprowadzenie do informatyki Wykład 6
Podstawowe pojęcia programowania współbieżnego
Mechanizmy pracy równoległej
Wykład nr 8: Zakleszczenia
Grażyna Mirkowska PJWSTK 15 listopad 2000
Wykład 10 Metody Analizy Programów Specyfikacja Struktur Danych
Wykonał : Marcin Sparniuk
Semafory Autorzy : Michał Winciorek Łukasz Jackowicz.
PROGRAMOWANIE STRUKTURALNE
PROGRAMOWANIE STRUKTURALNE
Badania operacyjne. Wykład 1
SYSTEMY OPERACYJNE SYNCHRONIZACJA PROCESÓW
PRZERZUTNIKI W aktualnie produkowanych przerzutnikach scalonych TTL wyróżnia się dwa podstawowe rodzaje wejść informacyjnych: - wejścia asynchroniczne,
1 RISC – nasze założenia Podstawowe cechy: Wszystkie operacje są realizowane na rejestrach, Tylko operacje typu load i store wymagają dostępu do pamięci,
Podstawowe składniki funkcjonalne procesora i ich rola.
Procesy współbieżne Copyright, 2004 © Jerzy R. Nawrocki Teoretyczne podstawy informatyki.
Procesy współbieżne Copyright, 2005 © Jerzy R. Nawrocki Wstęp do informatyki.
SEMAFORY Dominik Niewiadomy Łukasz Dąbrowski.
Wykład nr 7: Synchronizacja procesów
Systemy operacyjne Wykład nr 4: Procesy Piotr Bilski.
Wykład nr 2: Struktura systemu komputerowego a system operacyjny
Komputer, procesor, rozkaz.
Temat nr 10: System przerwań
Semantyki programów współbieżnych " Determinizm programów sekwencyjnych, " Nie-determinizm programów współbieżnych, " prawdziwa równoległość vs.przeploty.
Projektowanie i programowanie obiektowe II - Wykład IV
Wstęp do interpretacji algorytmów
ZARZĄDZANIE PROCESAMI
6. SZEREGOWANIE PROCESÓW
Muteksy Muteksy (mutex – MUTual EXclusion) są prostymi obiektami synchronizacyjnymi pełniącymi rolę semaforów binarnych dla wątków (chroniącymi sekcje.
Semafory według normy POSIX
8. LOGIKA TEMPORALNA Składnia zdaniowej logiki temporalnej:
Programowanie współbieżne
RODZAJE KOMUNIKACJI MIĘDZY PROCESAMI
Budowa algorytmów Algorytm: skończony ciąg operacji wraz z ściśle sprecyzowanym porządkowaniem ich wykonywania, które po realizacji dają rozwiązanie dowolnego.
Podstawy programowania
Pliki tekstowe. Operacje na plikach. mgr inż. Agata Pacek.
Systemy operacyjne.
Budowa systemu komputerowego
Pliki Pojęcie i rodzaje plików Definicja typu plikowego Operacje wykonywane na plikach elementowych.
Autor: Justyna Radomska
SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Automatyka i Robotyka Systemy czasu rzeczywistego Wykład 4.
Architektura komputerów
Problem sekcji krytycznej
Przerwanie ang. interrupt.
Maszyna wirtualna ang. virtual machine, VM.
Buforowanie D e f i n i c j a.
Koncepcja procesu Zadanie i proces. Definicja procesu Process – to program w trakcie wykonywania; wykonanie procesu musi przebiegać w sposób sekwencyjny.
Wykład 10 typ zbiorowy rekurencja.
Wykład 7 Synchronizacja procesów i wątków
Procesy współbieżne Copyright, 2005 © Jerzy R. Nawrocki Wstęp do informatyki.
W ą t e k (lekki proces) thread.
SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Bariery synchronizacyjne Bariery są obiektami synchronizacyjnymi pakietu pthread służącymi do wyrównywania czasów pracy wątków wykonujących wspólne zadanie.
Systemy rozproszone  Rozdzielenie obliczeń między wiele fizycznych procesorów.  Systemy luźno powiązane – każdy procesor ma lokalną pamięć; procesory.
Algorytmika.
Obliczalność czyli co da się policzyć i jak Model obliczeń maszyna licznikowa dr Kamila Barylska.
Diagram aktywności (czynności)
Procesor, pamięć, przerwania, WE/WY, …
Diagram czynności Diagram czynności (activity diagram) służy do modelowania dynamicznych aspektów systemu. Diagram czynności przedstawia sekwencyjne lub.
Procesy, wątki Program a proces Proces: Przestrzeń adresowa, kod, dane, stos (część pamięci do przechowania zmiennych lokalnych i niektórych adresów) Otwarte.
Projektowanie obiektowe. Przykład: Punktem wyjścia w obiektowym tworzeniu systemu informacyjnego jest zawsze pewien model biznesowy. Przykład: Diagram.
Struktura systemu operacyjnego
Tryby adresowania i formaty rozkazów mikroprocesora
Wstęp do programowania Wykład 7
Programowanie strukturalne i obiektowe Klasa I. Podstawowe pojęcia dotyczące programowania 1. Problem 2. Algorytm 3. Komputer 4. Program komputerowy 5.
Zapis prezentacji:

4. TEORETYCZNE MODELE PROCESÓW WSPÓŁBIEŻNYCH Teoretyczne modele uwzględniają wybrane cechy rzeczywistych procesów, stanowiąc kompromis pomiędzy łatwością i jakością modelowania. Konstruując model obliczeń należy mieć na względzie: 1) czy korzystamy z pamięci dzielonej, czy z przesyłania komunikatów (raczej nie miesza sie tych dwóch rzeczy); 2) jakie akcje uznajemy za elementarne, to jest wykonywane niepodzielnie - niezależnie od akcji innych procesów. Przykład (Z. Manna, A. Pnueli) Obliczyć wartość dwumianu Newtona dla n, k naturalnych, n k. n! n · (n - 1) ·... · (n - k + 1) ( k czynników ) k! (n - k)! 1 2 ·... · k ( k czynników ) Wartość tego wyrażenia jest zawsze liczbą naturalną dla n, k takich, że n k.

Sposób obliczenia: współbieżnie wykonujemy mnożenia w liczniku i mianowniku, i na bieżąco wykonujemy dzielenia - wtedy, kiedy tylko jest to możliwe (ten sposób jest dobry, gdyż możemy uniknąć przekroczenia zakresu arytmetyki komputera, pomimo że licznik i mianownik oddzielnie mogłyby ten zakres przekroczyć). n, k - dane l, m - zmienne pomocnicze, przyjmujące odpowiednio wartości l : n, n-1,..., n - k + 1 m: 1,2,..., k b - wartość ułamka (na początku b = 1) Proces P 1 mnoży b przez kolejne wartości l, proces P 2 dzieli b przez kolejne wartości m, ale dopiero wtedy, kiedy jest to wykonalne: w żadnej chwili liczba wykonanych dzieleń nie może przekroczyć liczby wykonanych mnożeń, czyli musi zachodzić m n - l, aby można było wykonać dzielenie, zatem warunkiem wykonania dzielenia jest l + m n.

{ n, k : dane } l : n ; m : 1 ; b : 1 ; while l n - k do while m k do begin begin P 1 : b : b l ; || P 2 : await ( l + m ) n ; l : l - 1 b : b div m ; end ; m : m + 1 end; { b : wynik } Założenia: 1) zmienne n, k, b umieszczone są w pamięci wspólnej i oba procesy używają dla nich takich samych nazw; 2) sprawdzenia warunków oraz instrukcje podstawienia wykonywane są niepodzielnie.

Instrukcja await (wb), gdzie wb jest wyrażeniem boolowskim, zawiesza wykonywanie procesu do momentu, gdy zacznie zachodzić wb = true. Gdyby działanie await (wb) było interpretowane jako: wb ? T F byłoby to tak zwane aktywne czekanie (ciągłe sprawdzanie wartości wb absorbuje moc oblicze- niową procesora). W praktyce częściej następuje zawieszenie wykonywania procesu przez system operacyjny tak, aby nie marnować mocy procesora, więc bardziej adekwatnym schematem byłby schemat: wb ? T F

Działanie programów sekwencyjnych często przedstawiane jest za pomocą schematów blokowych. Dla programów współbieżnych dogodniejszą formą ilustracji ich działania są diagramy przejść. stan przejście c ? instr warunek logiczny instrukcja (strażnik przejścia) wykonywana niepodzielnie Jeżeli dla każdego stanu zachodzi, że wszystkie przejścia wychodzące z tego stanu mają warunki parami wykluczające się, program nazywamy procesowo deterministycznym. Omawiany przykład jest procesowo deterministyczny. s

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 5 m = 1 b = 1 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 5 m = 1 b = 1 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 5 m = 1 b = 1 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 5 m = 1 b = 5 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 1 b = 5 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 1 b = 5 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 1 b = 5 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 1 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 1 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 2 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 4 m = 2 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 3 m = 2 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 3 m = 2 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 3 m = 2 b = 20 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 3 m = 2 b = 10 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 3 m = 2 b = 30 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 2 b = 30 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 3 b = 30 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 3 b = 30 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 3 b = 30 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 3 b = 10 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 3 b = 10 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 4 b = 10 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

l n - k ? m k ? m: m +1l: l -1 n = 5 k = 3 l = 2 m = 4 b = 10 p0p0 p1p1 p2p2 p3p3 r0r0 r1r1 r2r2 r3r3 r4r4 b: b l m k ? l + m n ? b : b div m

W powyższym diagramie pojedyncze strzałki odpowiadają pojedynczym operacjom niepodziel- nym. Wielkość jednostek syntaktycznych programu, o których możemy założyć, że będą wyko- nane niepodzielnie, nazywamy ziarnistością (granularity). Przedstawiony program charakteryzuje się niedeterminizmem wykonania, gdyż jego wykonanie może być modelowane przez różne przeploty operacji niepodzielnych obu procesów, np. P 1 P 1 P 2 P 1 P 2 P lub P 1 P 1 P 1 P 2 P 1 P Natomiast pomimo to stan końcowy programu (wektor wartości zmiennych i wskaźników instrukcji) jest w każdym przypadku taki sam, niezależnie od wykonanego przeplotu - taki program nazywamy zdeterminowanym (wszystkie współbieżne programy transformacyjne powinny posiadać tę cechę).

W przypadku korzystania ze wspólnej pamięci efekt wykonania programu współbieżnego może zależeć od ziarnistości. Przykład {y = 1 - wartość początkowa} P 1 : y = y + 1 P 2 : y = y - 1 Jeżeli założymy, że instrukcje podstawienia wykonywane są niepodzielnie, to zarówno dla prze- plotu P 1 P 2, jak i P 2 P 1 wynikiem wykonania będzie y = 1. W praktyce kompilator może przełożyć te instrukcje na następujące ciągi rozkazów maszynowych: LOAD Rejestr1, y LOAD Rejestr2, y P 1 : ADD Rejestr1, #1 P 2 : SUB Rejestr2, #1 STORE Rejestr1, y STORE Rejestr2, y (Zakładamy, że każdy proces używa swojego lokaknego rejestru).

Zakładając, że wszystkie przeploty rozkazów z przekładów P 1 i P 2 są dopuszczalne, otrzymujemy trzy różne wyniki dla różnych przeplotów: P 1 P 1 P 1 P 2 P 2 P 2 y = 1 Liczba wszystkich przeplotów ciągu P 1 P 1 P 2 P 1 P 2 P 2 y = 0 m - elementowego z ciągiem n - elementowym P 1 P 2 P 1 P 2 P 2 P 1 y = 2 (m + n) ! m ! n ! (inne przeploty dałyby jeden z tych trzech wyników). Zmniejszenie ziarnistości spowodowało zatem, że program przestał być zdeterminowany. W języku inżynierskim zjawisko, kiedy wynik zależy od przypadkowych czasów wykonania (lub, dla układów scalonych, od przypadkowych różnic w czasach propagacji sygnałów elektrycznych) nazywane jest hazardem. Nie należy projektować niczego, czego efekt wykonania mógłby zależeć od hazardu ! wynosi

Powyższy przykład był prosty, bo wszystkie występujące w nim rozkazy maszynowe co najwyżej raz wykonywały cykl pamięciowy. Jego analiza odnosi się więc zarówno do wykonania z przeplo- tem (drobnoziarnistym) na pojedynczym procesorze, jak i do wykonania równoległego na dwóch procesorach mających dostęp do wspólnej pamięci. Różnica mogłaby wystąpić w przypadku, gdyby dwa procesory równolegle wykonywały rozkazy wymagające dwóch odwołań do pamięci - np. rozkaz dodania zawartości akumulatora do zawartości komórki pamięci z pozostawieniem wyniku w pamięci. W takim przypadku do modelowania należałoby stosować jeszcze drobniejszą ziarnistość - na poziomie mikrorozkazów (operacjami niepodzielnymi są odczyt / zapis z /do pamięci i wykonanie operacji na samych rejestrach).

5. NISKOPOZIOMOWE MECHANIZMY ZAPEWNIANIA NIEPODZIELNOŚCI OPERACJI Możliwość zapewnienia niepodzielności operacji (będących ciągami operacji elementarnych) na komórkach pamięci wspólnej jest w programowaniu współbieżnym sprawą o zasadniczym zna- czeniu. Szczególnie w przypadku rzeczywistej równoległości widoczna jest potrzeba zabezpiecze- nia pojedynczym procesom prawa wyłączności dostępu (na pewien czas) do zmiennych dzielonych, ale w przypadku drobnoziarnistego przeplotu też to jest istotne. Ciąg instrukcji programu operujących na współdzielonych zasobach (pamięci dzielonej, wspólnych plikach itp.), który powinien być wyko- nany niepodzielnie, nazywamy sekcją krytyczną programu. Jakie są sposoby zabezpieczania sekcji krytycznych ? Jeżeli współbieżność jest symulowana na pojedynczym procesorze przez system operacyjny i sekcje krytyczne nie są związane z pamięcią wspólną, ale innymi zasobami (pliki, kolejki), proste operacje na tych zasobach są dostępne w postaci wywołań funkcji systemowych. Funkcje systemowe są wykonywane przez jądro systemu na zamówienie procesu i niepodzielność ich wykonania jest zapewniana przez system operacyjny.

Jeżeli mają być wykonywane operacje na pamięci wspólnej, lub bardziej złożone operacje na dowolnych zasobach, programista musi sam zadbać o ich zabezpieczenie. Najprostszym mecha- nizmem abstrakcyjnym służącym do tego celu są semafory. Podstawowym rodzajem semafora jest semafor binarny, będący obiektem, którego jedyne pole może przyjmować tylko wartości 0 i 1, a jedyne operacje, jakie można na nim wykonać, to: P (czekaj) V (sygnalizuj) Definicje tych operacji jest następująca: P(S) - jeżeli S>0, to zmniejsz S o 1, w przeciwnym razie wstrzymaj wykonywanie procesu; V(S) - jeżeli są jakieś procesy wstrzymane przez semafor S, to wznów jeden z nich, w przeciwnym razie jeśli S=0, to zwiększ S o 1.

Uwaga. 1) Skutek próby otwarcia otwartego semafora binarnego zależy od implementacji. Dojście do takiej sytuacji świadczy o błędzie w programie (i system operacyjny zazwyczaj reaguje sygnalizacją błędu). 2) Same operacje na semaforach muszą być wykonywane niepodzielnie. W systemach z przeplo- tem realizowane są jako funkcje systemowe, natomiast w sytuacji rzeczywistej równoległości ich implementacja musi być wspierana przez odpowiedni sprzęt (procesory z niepodzielnymi rozkazami typu test-and-set). 3) Niedeterminizm uruchamiania procesów czekających pod semaforem może podlegać różnym ograniczeniom (pojęcia związane z szeregowaniem wykonywania procesów będą omówione na następnym wykładzie).

Przykład Użycie semafora binarnego do zabezpieczenia sekcji krytycznej w przypadku dwóch procesów. {na początku S=1} while true do while true do begin begin niekrytyczna1; niekrytyczna2; P 1 : czekaj(S); || P 2 : czekaj(S); krytyczna1; krytyczna2; sygnalizuj(S) sygnalizuj(S) end end Uwaga. Przyjmujemy założenie, że każde wykonanie zarówno sekcji krytycznej, jak i niekrytycznej zajmuje skończony czas (procesy nie zapętlają się w nich ani nie zawieszają).

{ S = 1 } niekrytyczna1 krytyczna1 S > 0 ? S = 0 S := S+1 niekrytyczna2 S > 0 ? S = 0 krytyczna2 S = S+1 Uwaga. Gdyby w powyższym przykładzie zrównoleglić trzy takie procesy lub więcej, wzajemne wykluczanie byłoby dalej zapewnione, ale jeden z procesów mógłby zostać zagłodzony.

Uogólnienia semafora binarnego: 1) semafor ogólny - różni się od binarnego tym, że może przyjmować dowolne wartości naturalne, zaś operacja V, jeżeli nie czeka żaden proces, zwiększa zawsze wartość S o 1; 2) semafor ograniczony - może przyjmować wartości naturalne z zakresu od 0 do pewnego n. Zawieszenie procesu powoduje zarówno próba zmniejszenia wartości semafora poniżej 0, jak i próba zwiększenia powyżej n ; 3) semafor wielokrotny - pozwala na wykonywanie niepodzielnych operacji na wielu wartościach jednocześnie (będzie omówiony przy okazji opisu implementacji w systemie Linux). Uwaga. W językach programowania dysponujących standardowymi zestawami instrukcji wszystkie rodzaje semaforów są wzajemnie zastępowalne. Do rozwiązania konkretnych problemów jedne rodzaje mogą jednak być wygodniejsze, niż inne.

Przykład Jeżeli w sieci lokalnej jest 5 ogólnodostępnych drukarek, to dostęp wielu procesów do nich można skoordynować przy użyciu semafora przyjmującego wartości Przykład Problem producenta i konsumenta z n - miejscowym buforem cyklicznym. while true do while true do begin begin produkuj(e); czekaj(elementy); czekaj(miejsca); e := bufor(wy); P 1 : bufor(we) := e; P 2 : wy := (wy + 1) mod n; we := (we + 1) mod n; sygnalizuj(miejsca); sygnalizuj(elementy) konsumuj(e) end end producentkonsumentbufor

W przypadku komunikacji przez kanał przyjmujemy, że dostępne są niepodzielnie wykonywane funkcje send(, expr) i receive(, e), gdzie e jest zmienną, expr jest wyrażeniem tego samego typu, co e, a jest kanałem mogącym pomieścić ciąg elementów tego samego typu, co e. Kanał może mieć pojemność skończoną (w szczególnym przypadku 0) lub nieskończoną. Funkcja send zawiesza wyko- nywanie procesu, jeśli kanał jest pełny, funkcja receive zawiesza proces przy próbie pobrania z kanału pustego. Przykład Rozwiązanie problemu producenta i konsumenta przy użyciu kanału. while true do while true do begin begin P 1 : produkuj(e); P 2 : receive(, e); send(, e) konsumuj(e) end end

Monitory są deklarowalnymi obiektami mającymi zagwarantowaną niepodzielność wykonywania ich metod. Jest zatem niemożliwe współbieżne wykonanie operacji w jednym monitorze, ale możliwe w kilku różnych monitorach. Monitory są bardzo naturalnym mechanizmem ochrony sekcji krytycz- nych.