Esercizio - Valori finali di x e y con semafori e processi concorrenti (eserciziario, esercizi 99 e 110)
In questa pagina 3
Esercizio 99. Tre processi , , si sincronizzano con i semafori Sem1, Sem2, Sem3 (inizializzati a 0) e operano sulle variabili condivise , , inizializzate a , , :
Process A { Process B { Process C {
P(Sem1); P(Sem2); V(Sem2);
z = (x - z) * y; x = x + y; P(Sem3);
x = x + z + y; z = x - z; x = x / y;
V(Sem3); y = (y - z) + x; y = 2*z + x;
P(Sem1); Print(y); V(Sem1);
x = x + y; V(Sem1); z = x + z;
Print(x); } Print(z);
} }Con quale ordine i processi stampano i valori? Qual è il valore finale delle tre variabili?
Esercizio 110. Due processi condividono la variabile ( inizialmente); = wait, = signal; SemA e SemC sono inizializzati a 0, SemB e Mutex a 1.
P1: P2:
1: P(SemA) 8: P(SemB)
2: P(Mutex) 9: P(Mutex)
3: if (x < 0) x = x + 1 10: x = x - 2
4: V(Mutex) 11: V(Mutex)
5: V(SemC) 12: V(SemA)
6: P(SemA) 13: P(SemC)
7: print(x) 14: P(Mutex)
15: x = x - 1
16: V(Mutex)
17: print(x)I due processi sono eseguiti in modo concorrente. Si elenchino i possibili ordini di esecuzione delle istruzioni (per esempio 1 8 2 10 ...) motivando la risposta.
Esercizio 99
Chi parte e chi aspetta. attende Sem2, che solo incrementa con la sua prima istruzione: quindi parte per primo, poi . attende Sem1, incrementato solo da (alla fine) e da (dopo P(Sem3)). attende Sem3, incrementato da . Quindi il primo V(Sem1) viene necessariamente da (quello di è dopo P(Sem3), che richiede il V(Sem3) di , che richiede un V(Sem1)): l'ordine delle fasi è .
Calcolo passo-passo ():
| passo | processo | istruzione | stampa | |||
|---|---|---|---|---|---|---|
| 0 | iniziale | 1 | 2 | 1 | ||
| 1 | V(Sem2) |
1 | 2 | 1 | ||
| 2 | x = x + y |
3 | 2 | 1 | ||
| 3 | z = x - z |
3 | 2 | 2 | ||
| 4 | y = (y - z) + x = (2-2)+3 |
3 | 3 | 2 | ||
| 5 | Print(y) |
3 | 3 | 2 | 3 | |
| 6 | V(Sem1) |
|||||
| 7 | P(Sem1); z = (x - z) * y = (3-2)*3 |
3 | 3 | 3 | ||
| 8 | x = x + z + y = 3+3+3 |
9 | 3 | 3 | ||
| 9 | V(Sem3) |
|||||
| 10 | P(Sem3); x = x / y = 9/3 |
3 | 3 | 3 | ||
| 11 | y = 2z + x = 6 + 3 |
3 | 9 | 3 | ||
| 12 | V(Sem1) |
Da qui in poi (seconda parte) e (ultime due istruzioni) sono concorrenti:
- :
P(Sem1)passa,x = x + y = 3 + 9 = 12,Print(x)stampa 12; - :
z = x + z: se lo esegue prima dell'aggiornamento di di , ; se dopo, ;Print(z)stampa 6 oppure 15.
Risposte. Il processo stampa per primo. Non si può dire chi stampa per secondo e per terzo tra () e ( oppure ). Stato finale: , , oppure (a seconda di quale processo avanza per primo tra e ). L'enumerazione di tutti gli intrecci conferma le quattro combinazioni: output o con e in entrambi gli ordini.
Errore nella soluzione del corso. La slide scrive "il risultato finale sarà e ": ma vale 9 alla fine (l'istruzione y = 2z + x di lo porta a 9 e nessuno lo cambia più; nella stessa slide il passo è annotato = 9). Il valore corretto è .
Esercizio 110
Si ragiona sui semafori:
P1istruzione 1 attendeSemA(0): si sblocca solo conV(SemA)diP2(istruzione 12);P2può iniziare subito:SemB = 1,Mutex = 1.
Sequenza forzata. P2 esegue 8, 9, 10, 11, 12 (nessuno lo interrompe in modo significativo: P1 è bloccato su 1 finché non c'è 12). Dopo 12 P1 può proseguire e P2 va a 13, che attende SemC (0), incrementato solo da P1 all'istruzione 5. Quindi: P1 esegue 1, 2, 3, 4, 5 (per x: dopo 10 vale , x < 0 è vero, quindi 3 porta a 0); poi P2 completa 13, 14, 15, 16, 17 (, stampa ).
Ordine completo. , con le istruzioni di P1 1 .. 5 che possono anche iniziare ("1" bloccato) prima di 8 (cioè P1 esegue P(SemA) e resta fermo): quello che conta è il momento in cui l'istruzione 1 termina, che è dopo 12. Il corso elenca "8:12 oppure 1 8:12 ... dopo 12 può esserci 2 oppure 13 ... in 13 sicuro P2 si blocca", cioè più "ordini" che differiscono solo per il momento in cui si comincia a tentare l'istruzione bloccata; nell'ordine di completamento l'ordine è unico.
Lo stallo finale. Dopo 17 P2 termina; P1 è alla istruzione 6, P(SemA): SemA vale 0 (c'è stato un solo V(SemA), all'istruzione 12, già consumato dall'istruzione 1) e nessun processo lo incrementerà più: P1 resta bloccato per sempre e non stampa mai (istruzione 7). Il corso non lo segnala; con i valori dati il sistema finisce in deadlock (parziale: termina P2, resta bloccato P1). Output: solo P2 stampa . Verificato enumerando tutti gli intrecci: l'unica traccia completa è quella indicata, e termina sempre con P1 bloccato su 6.
Domande d'esame
In 99, perché alla fine e non 3?
Traccia. è modificato da (porta a 3) e poi da con y = 2z + x ; dopo non viene più cambiato. Il valore 3 è quello stampato da , non il finale.
Versione ripasso
- 99 (; Sem1..3 = 0). Fasi forzate:
V(Sem2)(, stampa 3,V(Sem1)) (, ,V(Sem3)) (, ,V(Sem1)) (, stampa 12) e ( o , stampa) in qualunque ordine. Teoria: Semafori, monitor e problemi classici di sincronizzazioneUn semaforo è un intero accessibile solo con due operazioni atomiche, wait (P: aspetta finché S > 0 e decrementa) e signal (V, in POSIX sem_post: incrementa); il semaforo contatore ha valori illimitati, quello binario vale 0 o 1; con valore iniziale 1 realizza la mutua esclusione, con valore iniziale 0 impone un ordine di esecuzione (S1 prima di S2); senza attesa attiva ogni semaforo ha una coda di processi sospesi (sleep e wakeup); i semafori si usano male con facilità (ordine sbagliato, omissioni); il monitor è un tipo di dato astratto in cui un solo processo alla volta è attivo e le variabili condizione x.wait()/x.signal() sospendono e risvegliano (in POSIX mutex più pthread_cond_t); le anomalie di liveness sono deadlock, starvation e inversione di priorità; i problemi classici sono produttore-consumatore a buffer limitato (mutex, vuote = n, piene = 0; l'ordine delle wait è importante), lettori-scrittori (rw_mutex, mutex, read_count; i lettori possono far morire di fame gli scrittori) e filosofi a cena (la soluzione ingenua con un semaforo per bacchetta va in deadlock; si evita limitando a n-1 filosofi, rompendo la simmetria o ordinando le risorse), con soluzioni in C (POSIX) e in Go (canali e sync).Semafori, monitor e problemi classici di sincronizzazione →. - Finale 99: , (il corso dice 3: errore), o . stampa per primo.
- 110:
P1bloccato in 1 fino a 12. Ordine di completamento unico: 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 13, 14, 15, 16, 17. : 1 (10) 0 (3) (15); stampa . - Deadlock:
P1resta bloccato suP(SemA)(6) per sempre (un soloV(SemA)): non stampa mai. - Metodo: capire chi sblocca chi (grafo di precedenza), poi calcolare le variabili nell'ordine forzato.
- 99, ordine forzato: aspetta
Sem2( lo incrementa per primo); aspettaSem1; aspettaSem3( lo incrementa). Il primoV(Sem1)può venire solo da (quello di è dopoP(Sem3), che dipende da ): fasi . - 99, passaggi: : , , ; : , ; : , ; : ; : (se prima di ) o (dopo).
- 110, semafori:
SemA=SemC=0,SemB=Mutex=1;P1bloccato in 1 fino aV(SemA)(12);P2bloccato in 13 fino aV(SemC)(5): ordine di completamento 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 13, 14, 15, 16, 17; il corso elenca varianti che differiscono solo dall'istante in cui si tenta l'istruzione bloccata. - 110, valori: : 1, poi (10), poi 0 (3, perché ), poi (15):
P2stampa ;P1si ferma in 6 suP(SemA)(un soloV(SemA)): deadlock parziale, non stampa mai. - Errori tipici: non vedere che il primo
V(Sem1)viene da ; scambiare il valore stampato con il valore finale (); non accorgersi del blocco finale diP1.