Documente Academic
Documente Profesional
Documente Cultură
Realizarea practică a unui sistem de ceasuri logice presupune folosirea pentru fiecare
proces A a unei variabile cl, a cărei valoare se măreşte la producerea evenimentelor şi,
pentru fiecare mesaj, a unui câmp care să indice momentul transmiterii sale. Ceasurile
logice sunt incrementate conform următoarelor reguli:
(1) când A transmite un mesaj, el incrementează cl cu 1 şi apoi actualizează timpul tt
asociat mesajului la valoarea lui cl;
(2) când A primeşte un mesaj având asociat timpul tt, el actualizează cl la valoarea
maximă dintre cl şi tt + 1 şi apoi incrementează cl cu 1.
112
Folosind ceasurile logice, putem asocia un moment de timp fiecărui eveniment.
Pentru send acesta este timpul înregistrat în mesaj. Pentru receive acesta este valoarea
lui cl din procesul receptor după actualizarea la maximul dintre cl şi tt+1 şi
incrementarea ei. Aceasta asigură că, dacă un eveniment a se produce înaintea unui
eveniment b, timpul asociat lui a să fie mai mic decât timpul asociat lui b. Se induce
astfel o ordonare parţială pe mulţimea evenimentelor unui program.
Figura 8.2 Valorile de timp logic asociate evenimentelor din Figura 8.1
Deoarece două evenimente din procese diferite pot avea acelaşi timp logic de
producere (de exemplu, evenimentele a şi e din Figura 8.2), pentru a obţine o
ordonare totală se poate recurge la ordonarea proceselor şi la dispunerea
evenimentelor cu acelaşi timp logic în ordinea proceselor corespunzătoare.
113
Ca aplicaţie, prezentăm utilizarea ordonării totale a evenimentelor în realizarea
excluderii mutuale într-un sistem cu transmitere asincronă de mesaje, prin semafoare
distribuite. Soluţia are la baza următorul mecanism: când un proces execută o operaţie
P (sau V) el difuzează mesaje celorlalte procese, analizând răspunsurile acestora
pentru a determina continuarea execuţiei. Pentru a simplifica notaţia, folosim forma:
broadcast ch(m)
pentru a transmite mesajul m pe fiecare din canalele unui tablou ch[1:n].
+----------------+
+-------->¦ Utiliz[i] ¦--->-+
¦ +----------------+ ¦+----<-- Utiliz[j]
¦ ¦¦ Ajutor[j]
+---+ +---+
+---+ start[i] +---+ opsem[i]
+---+ +---+
¦ +----------------+ ¦
+----<----¦ Ajutor[i] ¦<----+
+----------------+
Figura 8.3
Fiecare proces Ajutor are o coadă locală de mesaje qm şi un ceas logic cl. Când un
proces Ajutor primeşte un mesaj P sau V, el îl memorează în qm, care este ordonată
după momentele de timp conţinute de mesaje (cu amendamentul suplimentar asupra
ordonării proceselor). Mesajele unor procese diferite nu sunt recepţionate în aceeaşi
ordine de toate procesele Ajutor. Mai mult, un mesaj cu un timp mai redus poate fi
recepţionat după un altul cu un timp mai mare. Dar, mesajele trimise de un acelaşi
proces vor fi recepţionate de celelalte procese în ordinea generării şi vor avea
momente de timp crescătoare. Ca urmare, dacă qm conţine un mesaj m cu timpul ts şi
procesul recepţionează mesaje cu un timp mai mare de la toate celelalte procese, este
sigur că nu va mai apare ulterior un mesaj cu un timp mai mic. În acest moment m
este complet confirmat şi, odată cu el, toate celelalte mesaje aflate în faţa lui în qm.
114
Acestea constituie un prefix stabil, nici un alt mesaj neputând fi inserat între cele din
prefix.
Utiliz(i: 1..n)::
var cl: int :=0; {ceas logic}
var ts: int;
...
cl := cl+1;
broadcast opsem(i, V, cl); {operatia V}
...
cl := cl+1;
broadcast opsem(i, P, cl); {operatia P}
receive start[i](ts);
cl := max(cl, ts+1); cl := cl+1;
...
Ajutor(i: 1..n)::
var qm: queue of (int, fel, int);
var cl: int := 0;
var sem: int := valoare_initiala;
var transm: int, k: fel, ts: int;
do true ->
receive opsem[i](transm, k, ts);
cl := max{cl, ts+1); cl := cl+1;
if k=P or k=V ->
115
insereaza (transm, k, ts) in locul corespunzator in qm;
cl := cl+1; broadcast opsem(i, ack, cl);
[] k=ack ->
inregistreaza transmiterea unui ack;
fa mesajele V complet confirmate ->
scoate mesaj din qm;
sem := sem+1;
af;
fa mesajele P complet confirmate st sem>0 ->
scoate mesaj (transm, k, ts) din qm;
sem := sem-1;
if tansm=i -> cl := cl+1; send start[i](cl) fi
af
fi
od
Un proces care doreşte să intre în secţiunea critică trimite mesaje de cerere request
tuturor celorlalte procese. Pentru a putea intra efectiv în secţiunea critică, este necesar
să primească de la fiecare câte un mesaj de răspuns reply. La recepţia unui mesaj
request, un proces poate determina dacă el sau procesul care a facut cererea ar trebui
să intre în secţiunea critică. Când el are prioritate, mesajul reply este întârziat; altfel,
el este transmis imediat procesului ce a generat cererea.
Figura 8.4 arată rezultatul aplicării acestor reguli pe exemplul din Figura 8.2.
Pe multimea vectorilor de amprente de timp, VT pot fi stabilite câteva relaţii. Fie VT1
şi VT2 doi vectori VT cu câte N elemente. Atunci,
117
Aplicaţie: Ordonare Cauzală Multicast
Presupunem că procesele unei colecţii P comunică între ele doar prin mesaje cu
difuzare (orice mesaj este trimis tuturor proceselor din colecţie). Se cere ca oricare
două mesaje m şi m' transmise în cadrul colecţiei să respecte dependenţa cauzală,
ceeace înseamnă că dacă mesajul m a fost trimis înaintea mesajului m' atunci, la orice
proces p din colecţie, livrarea lui m să aibă loc înaintea livrării lui m':
m -> m' Î livrarep (m) -> livrarep (m').
Pentru asta, fiecare proces foloseşte un protocol care întârzie eventual livrarea
mesajelor astfel încât aceasta să aibă loc în ordinea cauzală. Protocolul se bazează pe
o variantă uşor modificată a ceasurilor logice vectoriale, pe care o numim vectori de
timp pentru a face diferenţierea faţă de varianta de bază. În noua variantă, ceasurile
sunt avansate doar la operaţiile de transmitere de mesaje.
Amprenta vt(m) spune receptorului câte evenimente (din alte procese) au precedat m
şi ar putea influenţa cauzal pe m.
118
(m este următorul mesaj pe care d îl aştepta de la s)
vt(m) [k] =< V(d)[k] pentru k <> s
(toate mesajele primite deja de Ps când a trimis m au fost primite şi de Pd când acesta
a primit m).
Când mesajul este livrat, V(d) este actualizat conform regulilor vectorilor de timp:
V(d) [k] = max{V(d)[k], vt(m)[k]} pentru fiecare k = 1,n.
Livrarea mesajului m poate determina livrarea altor mesaje, primite anterior, care
acum îndeplinesc condiţia de cauzalitate.
119