Sei sulla pagina 1di 25

Sincronizzazione tra Thread

Problemi

1
I problemi della sincronizzazione tra Thread
Esiste un certo numero di Produttore/consumatore
problemi classici della (producer/consumer)
programmazione concorrente Lettori e scrittori
che rappresentano la casistica (readers/writers)
completa delle diverse situazioni 5 loso a cena (dining
di concorrenza; possono essere
philosophers)
suddivisi in 5 macro problemi, dei
Barbiere dormiente (sleeping
quali riportiamo il nome con il
quale sono indicati nella barber)
letteratura informatica:

2
Problema del produttore e consumatore 1
un esempio classico di sincronizzazione tra
processi.
Il problema descrive due processi, uno produttore
(producer) ed uno consumatore (consumer), che
condividono un buffer comune, di dimensione
ssata.
Compito del produttore generare dati da
depositare nel buffer in continuo.
Contemporaneamente, il consumatore utilizzer i
dati prodotti, rimuovendo di volta in volta dal
buffer.
Il problema assicurare che il produttore non
elabori nuovi dati se il buffer pieno, e che il
consumatore non cerchi dati se il buffer vuoto.

3
Problema del produttore e consumatore 2
Il problema evidenzia due Suddividiamo il problema in 3 casi:
problemi di sincronizzazione: Possiamo prima analizzare il caso
Evitare che un produttore inserisca particolare nel caso in cui ci sia un
unico produttore ed un unico
nel magazzino se esso pieno ed consumatore ed il buffer ha una
evitare che il consumatore preleva dimensione di un elemento.
dal magazzino se esso vuoto. Poi possiamo analizzare il caso in cui
Evitare che pi produttori ci sia un unico produttore ed un
inseriscono nel magazzino in unico consumatore ed il buffer ha
contemporanea ed evitare che pi una dimensione ssa diversa da 1.
consumatori prelevano lo stesso Poi possiamo analizzare il caso
pezzo in contemporanea. generale.

4
Problema del produttore e consumatore 2
Per gestire la sincronizzazione tra
processi ci servono due semafori
binari per la mutua esclusione
per segnalare se il buffer pieno
o vuoto.
I due riquadri sono i posti dove
vengono eseguite le primitive
V(S) e P(S) sui semafori binari.

5
Pseudocodice semaphore pieno = semaphore(0)

1 - semafori
semaphore vuoto = semaphore(1)

Processo produci()
Questo pseudocodice, inizio
P(vuoto)
rappresenta i due <produci il dato>
processi produci e V(pieno)
fine
consuma che
Processo consuma()
realizzano e inizio
consumano il dato, P(pieno)
<consuma il dato>
naturalmente V(vuoto)
fine

6
Problema del produttore e consumatore 3
Per gestire la sincronizzazione tra
processi ci servono due semafori per
segnalare se il buffer pieno o vuoto.
Il valore massimo del semaforo la
dimensione del deposito (array),
mentre la minima 0. Si nota che i
possibili valori siano la dimensione del
deposito + 1.
I due riquadri sono i posti dove vengono
eseguite le primitive V(S) e P(S) sui
semafori.

7
Problema del produttore e consumatore 4
Naturalmente per gestire pi
thread dobbiamo mettere dei
semafori per il controllo delle
aree critiche: linserimento e la
rimozione di elementi.
Quindi in questo caso abbiamo
bisogno di ben 2 semafori e 2
semafori binari per gestire in
sicurezza e thread safe il tutto.

8
Pseudocodice semaphore pieno = semaphore(0)

2 - semafori semaphore vuoto = semaphore(1)


semaphore mutexProduci = semaphore(1)
semaphore mutexConsuma = semaphore(1)
Questo pseudocodice,
rappresenta i due Processo produci() Processo consuma()
Inizio
processi produci e inizio
P(mutexProduci) P(mutexConsuma)
consuma che P(vuoto) P(pieno)
realizzano e <produci il dato> <consuma il dato>
V(vuoto)
consumano il dato, V(pieno)
V(mutexProduci) V(mutexConsuma)
naturalmente fine fine

9
Problema del produttore e consumatore 5
I due riquadri blu sono i posti
dove vengono eseguite le
primitive V(S) e P(S) sui semafori
per gestire la dimensione del
magazzino.
I due riquadri verdi servono per
gestire in mutua esclusione le
aree critiche del multithreading.

10
Pseudocodice
3 - semafori
Questo pseudocodice,
rappresenta i due
processi produci e
consuma che
realizzano e
consumano il dato,
naturalmente ed un
buffer a dimensione
nita 11
Pseudocodice
4 - monitor
Unaltra soluzione del
problema quella di usare i
monitor, che semplicano di
molto il codice. La struttura
non cambiata molto, ma il
codice si semplicato,
nonostante ricordo che in
questo caso la gestione della
coda stata sorvolata.

12
Problema dei lettori e scrittori 1
In un sistema sono presenti due gruppi di In questo caso pi lettori possono
processi, i lettori e gli scrittori: contemporaneamente utilizzare un dato
senza danneggiarlo:
I lettori non possono editare i dati,
Quindi un lettore pu accedere a un dato
ma solo leggerli in modo non anche se gi presente un altro lettore
distruttivo il contenuto di un buffer
per elaborarlo; Mentre lo scrittore deve accedere in modo
esclusivo come nellesempio della lezione
Gli scrittori possono invece produrre precedente.
un dato e quindi aggiornare il Esiste un vincolo di mutua esclusione fra
contenuto del buffer. lettori e scrittori nelluso della risorsa e inoltre
gli scrittori tra loro si contendono la risorsa,
La situazione diversa da quella che quindi deve essere gestita in mutua
analizzata nella lezione precedente dei esclusione.
produttori / consumatori.

13
Problema dei lettori e scrittori 2
Prima soluzione - Ipotizziamo che: Le procedure necessarie a
i lettori possano accedere alla risorsa
anche se ci sono scrittori in attesa; realizzare la sincronizzazione di
uno scrittore possa accedere alla risorsa questo sistema sono quattro:
solo se questa libera.
Anche se lipotesi fatta sembra sensata, Una di richiesta lettura;
analizzando attentamente ci accorgiamo che Operazioni di lettura, esterne.
potrebbe portare a una situazione di
starvation da parte degli scrittori, in quanto se Una di ne lettura;
i lettori continuano ininterrottamente a
leggere, non potranno mai accedere in Una di richiesta scrittura;
scrittura sul buffer.
Operazioni di scrittura, esterne.
Una di ne scrittura.

14
Pseudocodice
1
Questo pseudocodice
rappresenta la soluzione,
in pseudocodice, per la
prima idea di come
risolvere il problema dei
scrittori/lettori. Come si
nota il grosso problema
che ci pu essere un
unico scrittore

15
Problema dei lettori e scrittori 3
Una seconda soluzione che migliora la Una differenza rispetto alla prima soluzione
vita agli scrittori e lettori quella che mentre i lettori possono essere
presentata di seguito dove uno scrittore, contemporaneamente dentro la RC
prima di terminare le sue operazioni, cerca lettura/scrittura, gli scrittori
di passare il testimone a un altro scrittore devono susseguirsi uno alla volta, cio in
invece che ai lettori. mutua esclusione. Questo accesso
Il semaforo mutexScrittori serve per serializzato viene realizzato con un ulteriore
garantire la mutua esclusione sulla variabile semaforo, mutexScrittore.
numScrittori cos come il Le procedure di lettura rimangono
semaforo mutex regolava laccesso alla pressoch invariate rispetto alla soluzione
variabile numLettori nel caso prima precedente.
descritto.

16
Pseudocodice
2
Questo pseudocodice
risponde al problema di
pi lettori, si nota che il
codice dei lettori non
cambiato, mentre c un
profondo cambiamento
nel codice dei scrittori.

17
Problema dei lettori e scrittori 4
Ora il problema diventato doppio: possono bloccarsi sia i lettori che
gli scrittori, quindi non
abbiamo ancora risolto il problema.
La soluzione ottimale quella di alternare lettori e scrittori in modo
che entrambe le categorie
possano evolvere.

18
Problema dei 5 loso 1
5 loso sono seduti attorno a un
tavolo circolare; ogni losofo ha un
piatto di spaghetti tanto scivolosi che
necessitano di 2 forchette per poter
essere mangiati; sul tavolo vi sono in
totale 5 forchette.
Ogni losofo ha un comportamento
ripetitivo, che alterna due fasi:
una fase in cui pensa,
una fase in cui mangia.

19
Problema dei 5 loso 2
Quando un losofo ha fame:
I loso non possono mangiare 1. prende la forchetta a sinistra del piatto
tutti insieme: ci sono solo 5 2. poi prende quella che a destra del suo
piatto
forchette, mentre ne 3. mangia per un po
servirebbero 10; 4. poi mette sul tavolo le due forchette.
C Possibilit di deadlock: se tutti i loso
2 loso vicini non possono afferrasse contemporaneamente la forchetta di
sinistra, tutti rimarrebbero in attesa di un evento
mangiare contemporaneamente che non si potr mai vericare.
perch condividono una La situazione di starvation pu vericarsi
indipendentemente dal deadlock se uno dei loso
forchetta e pertanto quando uno non riesce mai a prendere entrambe le forchette.
mangia, l'altro costretto ad
attendere

20
Problema dei 5 loso 3
Ogni losofo verica se entrambe le
forchette sono disponibili:
in caso affermativo, acquisisce le
due forchette (in modo atomico);
in caso negativo, aspetta.
In questo caso non c possibilit di
deadlock.
La situazione di starvation pu
vericarsi indipendentemente dal
deadlock se uno dei loso non riesce
mai a prendere entrambe le forchette.

21
Problema del barbiere
Un negozio di barbiere ha un barbiere, Se tutte le sedie sono occupate, il cliente
una poltrona da barbiere e n sedie per i se ne va scocciato!
clienti in attesa. Possiamo vedere questo problema come
Se non ci sono clienti, il barbiere si mette un problema di produttore-consumatore.
sulla sedia da barbiere e si addormenta. I produttori sono i clienti, che
Quando arriva un cliente, sveglia il producono se stessi. E il consumatore
barbiere addormentato e si fa tagliare i il barbiere, che consuma un cliente alla
capelli sulla sedia da barbiere.
volta.
Se arriva un cliente mentre il barbiere sta
tagliando i capelli a un altro cliente, il
cliente si mette in attesa su una delle
sedie.

22
Pseudocodice
Questo pseudocodice,
rappresenta i due processi
barbiere e cliente. Come si
nota il codice relativamente
snello e molto simile a quello
dei produttori e consumatori.

23
Problema delle montagne russe
Supponiamo che ci siano n passeggeri (threads) e un
carrello delle montagne russe (altro thread). I passeggeri
arrivano alla giostra e si mettono in attesa che arrivi il
carrello che pu trasportare C passeggeri con C < n. Il
carrello parte solo quando pieno.
Dettagli restrittivi:
i passeggeri invocano board e unboard
il carrello invoca load, run e unload
i passeggeri non possono montare nch il carrello
non ha invocato load
il carrello non pu partire nch C passeggeri non
sono montati a bordo
i passeggeri non possono smontare nch il carrello
non ha invocato unload
ovvio che questo problema pu essere causa di deadlock.

24
boarders = 0
unboarders = 0 passeggero()
mutex1 = Semaphore(1) {
Pseudocodice mutex2 = Semaphore(1)
boardQueue = Semaphore(0)
board()
mutex1.wait()
unboardQueue = Semaphore(0)
Questo pseudocodice, invece allAboard = Semaphore(0) boarders += 1
allAshore = Semaphore(0) if boarders == C:
rappresenta una soluzione al allAboard.signal()
problema delle montagne russe boarders = 0
tramite semafori e funzioni carrello() mutex1.signal()
while(true)
wait/signal. {
unboardQueue.wait()
unboard()
load()
boardQueue.signal(C) mutex2.wait()
allAboard.wait() unboarders += 1
run()
if unboarders == C:
unload()
unboardQueue.signal(C) allAshore.signal()
allAshore.wait() unboarders = 0
} mutex2.signal()
} }

25