Il 0% ha trovato utile questo documento (0 voti)
5 visualizzazioni76 pagine

Classroom

La programmazione concorrente è un insieme di tecniche per gestire l'esecuzione simultanea di più processi in un sistema di calcolo. Essa implica la creazione di thread che comunicano e si sincronizzano, richiedendo meccanismi di gestione delle risorse e sincronizzazione per evitare conflitti e garantire la mutua esclusione. Problemi come deadlock e starvation devono essere affrontati per garantire un funzionamento efficiente dei processi concorrenti.

Caricato da

76nbsdrmxh
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
5 visualizzazioni76 pagine

Classroom

La programmazione concorrente è un insieme di tecniche per gestire l'esecuzione simultanea di più processi in un sistema di calcolo. Essa implica la creazione di thread che comunicano e si sincronizzano, richiedendo meccanismi di gestione delle risorse e sincronizzazione per evitare conflitti e garantire la mutua esclusione. Problemi come deadlock e starvation devono essere affrontati per garantire un funzionamento efficiente dei processi concorrenti.

Caricato da

76nbsdrmxh
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd

Programmazione

concorrente
Introduzione alla programmazione concorrente

L’espressione programmazione concorrente indica l’insieme


di tecniche e strumenti impiegati per descrivere il
comportamento di più attività o processi che si intende far
eseguire contemporaneamente in un sistema di calcolo.

Programmazione concorrente
Concetti fondamentali
● Programma: è un insieme di istruzioni che descrive le azioni
da compiere.
● Processo: rappresenta l’esecuzione delle azioni specificate
dal programma; un processo in esecuzione può cambiare il
proprio stato.
● Processore: è un dispositivo che consente l’evoluzione e il
completamento di un processo (la CPU). In
multiprogrammazione ogni utente ha l’impressione di
lavorare con un suo processore virtuale.

Programmazione concorrente
● Thread: è un segmento di istruzioni di un processo in
esecuzione. Un processo è un insieme di Thread che
rappresentano il suo codice eseguibile. Un processo è
composto come minimo da un thread, ma normalmente a
ogni processo ne vengono associati più di uno in base alle
capacità di avanzamento concorrente di ciascuno.
● Risorse del sistema: è un qualsiasi elemento hardware o
software che viene usato da un processo e che ne condiziona
la creazione o l’avanzamento.

Programmazione concorrente
Gestione delle risorse
Le risorse possono essere:
● prerilasciabili:
○ si possono sottrarre al processo che le sta usando prima
che esso le abbia rilasciate e senza causare il fallimento
della sua esecuzione;
○ il loro stato non si modifica durante l’utilizzo e può essere
salvato e successivamente ripristinato;
● non prerilasciabili:
○ non si possono sottrarre al processo che le sta usando
senza causarne il fallimento;
○ il loro stato non può essere salvato e ripristinato.
Programmazione concorrente
Per gestire la programmazione concorrente il sistema operativo
deve prevedere:
● un gestore della risorsa;
● un protocollo di accesso alla risorsa:
○ richiesta e assegnazione della risorsa;
○ utilizzo della risorsa;
○ rilascio della risorsa.

Programmazione concorrente
Programmi sequenziali e concorrenti
I programmi si possono classificare in sequenziali e
concorrenti: nel primo caso, l’esecuzione di un programma dà
luogo a un singolo processo, svolge una sola istruzione alla volta
sulla base di un programma sequenziale. Nel secondo caso, dà
luogo a più processi che competono tra loro per l’uso delle
risorse del sistema, vengono eseguite più istruzioni
contemporaneamente.
Da un punto di vista funzionale non vi è differenza tra i due tipi
di programmazione. I programmi concorrenti devono però fare
in modo che i vari processi si sincronizzino tra loro.

Programmazione concorrente
Processi concorrenti
I programmi concorrenti prevedono la creazione di più
processi (thread) che comunicano tra loro, si sincronizzano e
competono tra loro per le risorse di sistema.

Un programma concorrente prevede come requisiti tutti quelli


previsti da una normale elaborazione sequenziale più alcune
primitive di sistema per la creazione e la terminazione dei
processi e per consentire ai processi di sincronizzarsi e
comunicare tra di loro scambiandosi, al verificarsi di eventi, le
informazioni necessarie per poter cooperare.

Programmazione concorrente
In figura vediamo il processo P0 che
passa il controllo al processo P1, il
quale, quando ha terminato, restituisce
il controllo a P0.

Nella figura in basso figura vediamo


invece il caso in cui il processo P0
comunica dei dati ai processi P1, P2 e
P3, i quali, quando hanno terminato,
restituiscono il controllo.

Programmazione concorrente
Team di lavoro
In figura viene illustrato un’analogia
tra il mondo reale e un sistema di
elaborazione. Gli obiettivi si
raggiungono solo se i vari componenti
del team collaborano tra loro.
In generale si devono:
● pianificare le varie fasi di lavoro;
● coordinare le attività dei
componenti del team;
● predisporre le risorse necessarie;
● evitare conflitti per l’accesso a
eventuali risorse condivise.
Programmazione concorrente
Grafo delle precedenze

Processi paralleli
Per poter svolgere le attività in modo coerente, è opportuno
descrivere come i vari processi sono legati tra loro da rapporti
di precedenza tramite il grafo delle precedenze.
Si tratta di un grafo orientato in cui in ogni nodo viene
rappresentato un blocco di istruzioni, mentre le frecce indicano
la dipendenza di un blocco da un altro.

Programmazione concorrente
Per capire meglio il concetto
vediamo come esempio la
somma di 2 numeri.

Inizia
Leggi A
Leggi B
Calcola T = A + B
Stampa T
Fine

In figura è rappresentata la
sequenza delle operazioni (A) e
quella in cui si evidenziano le
attività parallele (B).

Programmazione concorrente
Programmazione concorrente
Programmazione concorrente
Grafo delle precedenze

Programmazione concorrente
Esecuzione concorrente di processi

In base al numero di processori fisici


disponibili si hanno due modalità per
far avanzare in modo concorrente i
processi:
● overlapping: i tempi delle
elaborazioni si accavallano;
● interleaving: i tempi delle
elaborazioni sono completamente
disgiunti.

Programmazione concorrente
Creazione ed eliminazione di processi

Un processo padre è un processo che ha creato uno o più processi


figli; ogni processo può creare molti figli ma può avere un solo padre.
Il costrutto che permette la creazione di un processo figlio viene
chiamato fork. Quando l’esecuzione di un processo incontra un punto
in cui può essere eseguito un altro processo in maniera parallela, il
sistema operativo esegue la primitiva fork e genera un processo figlio
che avanzerà indipendentemente dal padre.
Per eseguire una fork il sistema operativo crea un nuovo processo che
pone nello stato di pronto.
Programmazione concorrente
Il processo padre controlla il
completamento del processo
figlio con la primitiva join: esso
continua la sua esecuzione fino
alla chiamata alla primitiva join,
attraverso la quale attende la
conclusione del processo figlio.

Programmazione concorrente
Notazione cobegin/coend
Esiste un costrutto linguistico utilizzato per la descrizione di
esecuzioni concorrenti:

cobegin
S1(...)
S2(...)
....
Sn(...)
coend

Ogni istruzione viene eseguita in concorrenza e le istruzioni


che seguono il coend verranno eseguite, in maniera
sequenziale, solo quando tutte le istruzioni saranno terminate.
Programmazione concorrente
Sincronizzazione tra processi

La vera programmazione concorrente può avvenire solo con


sistemi multiprocessore. Nel caso di sistemi dotati di una
sola unità di elaborazione centrale, la contemporaneità è solo
simulata, poiché la CPU viene assegnata per quantità di tempo
fisse o variabili ai vari processi.
Uno dei principali campi di applicazione della programmazione
concorrente è costituito dalla realizzazione dei sistemi
operativi.

Programmazione concorrente
I processi possono essere più o meno “consapevoli” uno della
presenza dell’altro. Possono esistere infatti processi totalmente
“ignari” uno dell’altro, non progettati per lavorare insieme ma
che operano in un ambiente comune.
Se questi necessitano delle stesse risorse, si troveranno a
interferire tra loro, e sarà compito del sistema operativo
gestirli fornendo gli opportuni meccanismi di sincronizzazione.

Programmazione concorrente
L’ordine con cui due processi accedono a una risorsa condivisa
è importante perché, nel caso di dati condivisi, determina la
consistenza dei dati (race condition). La condizione impone
che un solo processo alla volta possa modificare i dati.
Il sistema operativo deve quindi gestire questa condizione
garantendo che:
● vi sia mutua esclusione, nel senso che se un processo sta
utilizzando una risorsa nessun altro processo può
appropriarsene;
● un processo che voglia accedere a una risorsa debba
attendere un tempo finito;
● non si verifichi la condizione di stallo: cioè che un processo
si blocchi in attesa di una risorsa che non potrà ottenere.
Programmazione concorrente
Competizione e cooperazione tra processi
L’interazione tra processi può essere di tipo:
● competitivo: due processi hanno la necessità di utilizzare
in modo esclusivo alcune risorse che servono a entrambi e
si trovano a competere per ottenerle;
● cooperativo: per svolgere uno specifico compito i processi
devono scambiarsi informazioni.

Programmazione concorrente
Sia per la cooperazione che per la competizione sono necessari
meccanismi di sincronizzazione e comunicazione:
● uso della memoria condivisa per far sì che alcuni dati di un
processo, se modificati, possano essere visti da un altro;
● scambio di messaggi per far sì che un processo possa
trasmettere informazioni a un altro.

Programmazione concorrente
Mutua esclusione
Quando è necessario che un solo processo alla volta abbia
accesso a un insieme di risorse comuni, si parla di mutua
esclusione tra processi concorrenti.
Dati due processi P1 e P2 e una risorsa R, si deve garantire
che:
1. in ogni istante, R sia libera oppure risulti assegnata a uno
solo tra P1 e P2 (mutua esclusione);
2. ciascuno dei due processi in esecuzione possa ottenere l’uso
della risorsa.

Programmazione concorrente
Per garantire queste condizioni è necessario che ogni processo
che utilizza una risorsa rispetti un protocollo articolato nelle
seguenti fasi:
1. richiesta della risorsa (necessaria per garantire la prima
condizione);
2. utilizzo della risorsa;
3. rilascio della risorsa (necessario per garantire la seconda
condizione).

Programmazione concorrente
Si definisce sezione critica
una parte di codice del
processo nella quale il
processo accede alla risorsa
per averne l’uso esclusivo.

Programmazione concorrente
Deadlock (stallo)
La realizzazione della mutua esclusione permette di evitare
problemi di interferenza tra processi, ma può causarne il
blocco permanente (deadlock). Questo avviene quando
ciascun processo attende che l’altro liberi una risorsa da lui
trattenuta.
Questa condizione è da evitare perché porta al blocco totale.
Nei sistemi informatici il deadlock è un problema che
coinvolge tutti i processi che utilizzano un certo insieme di
risorse. Se ne può uscire solo con metodi “distruttivi”,
mediante l’uccisione dei processi o riavviando la macchina.

Programmazione concorrente
Starvation (inedia)
Un altro caso che può verificarsi è quello in cui un processo
non può accedere a una risorsa perché questa risulta “sempre
occupata”.
Per esempio, se siete in coda dal salumiere e continuano ad
arrivare clienti disonesti, che vi passano davanti, non
riuscirete mai a farvi servire.
Si verificherà allora una condizione di starvation che, a
differenza del deadlock, non è una condizione definitiva ed è
possibile uscirne adottando un’opportuna politica di
assegnamento.
Programmazione concorrente
Realizzazione della mutua esclusione

Semafori e primitive di sincronizzazione


Un semaforo è una variabile intera non negativa. Alla variabile è
associata una lista di attesa Qs nella quale sono posti i descrittori dei
processi che attendono dal semaforo l’autorizzazione a procedere.
Un semaforo può essere di tipo binario, definito cioè da una variabile
binaria che può valere solo 1 oppure 0. Molto spesso un semaforo
binario assume il nome di Mutex.
La modifica di un semaforo binario (passaggio da 0 a 1 e viceversa)
viene effettuata invocando le primitive wait e signal. Per
convenzione un semaforo binario viene sempre inizializzato a 1 dal
sistema operativo, quindi inizialmente è verde.
Programmazione concorrente
Per gestire l’acquisizione e il rilascio di risorse in
mutua esclusione possiamo quindi utilizzare un
semaforo associato alla risorsa (SR) e i processi
possono modificare il valore del semaforo SR
tramite le due primitive wait(SR) e
signal(SR).

Programmazione concorrente
Nell’acquisizione delle risorse si
devono effettuare due
operazioni, una per controllare
lo stato del semaforo e l’altra
per porre il semaforo nello
stato di occupato.

Programmazione concorrente
Per realizzare la mutua
esclusione nell’accesso della
risorsa si fa precedere la
lock() e seguire la unlock()
all’uso della risorsa, come
mostrato in figura.

Programmazione concorrente
Per rendere mutuamente esclusive
la wait e la signal si può
procedere nel modo illustrato in
figura.

Programmazione concorrente
Produttore-consumatore

Classico esempio di sincronizzazione tra processi con accesso a una risorsa


condivisa (buffer limitato).

Compito del produttore: Compito del consumatore

• generare dati e depositarli nel • utilizzare i dati prodotti, prelevandoli


buffer di volta in volta dal buffer.

Occorre sincronizzare i due processi in modo che il produttore non depositi


nuovi dati se il buffer è pieno e che il consumatore non prelevi dati se il
buffer è vuoto.
Programmazione concorrente
Produttore-consumatore

Soluzione
• Sospendere il produttore se il buffer è pieno; sospendere il consumatore se il
buffer è vuoto

Produttore Consumatore

• verrà svegliato dal consumatore • verrà sospeso se il buffer è vuoto e,


(non appena questo avrà sarà risvegliato dal produttore non
prelevato un elemento dal buffer) appena questo avrà depositato dati
e comincerà a riempirlo nel buffer

Programmazione concorrente
Produttore-consumatore

Situazioni da evitare:
• un consumatore legge un dato senza che un produttore ne
abbia depositato alcuno
• un produttore sovrascrive un dato prima che il consumatore
sia riuscito a leggerlo
• un dato viene letto dai consumatori più di una volta

Si potrebbe avere una situazione di stallo, come nel caso in cui


entrambi i processi aspettino di essere risvegliati

Programmazione concorrente
Produttore-consumatore
Soluzione algoritmica
• due semafori
• dep (0 – blocca il consumatore)
• prel (1 – dà via libera al produttore)

Produttore Consumatore

• Se semaforo cons libero (1), • Se semaforo prod libero (1), blocca la


blocca la risorsa risorsa
• wait su prel (prel=prel-1) • wait su dep (dep=dep-1)

• Deposita dato nel buffer e • preleva un dato e sblocca la risorsa


sblocca la risorsa • signal su prel (prel=prel+1)
• signal su dep (dep=dep+1)

Programmazione concorrente
Produttore-consumatore

Soluzione algoritmica

Programmazione concorrente
Produttore-consumatore

Soluzione algoritmica

Programmazione concorrente
Il problema dello stallo (deadlock)

Mutua esclusione

Interferenza Blocco permanente


• interazione tra processi
NON prevedibile e NON desiderata

• Stallo
• due o più processi si ostacolano a vicenda impedendosi reciprocamente di portare a
termine la propria evoluzione
• I processi coinvolti nel deadlock ostacolano anche eventuali altri processi
• Le risorse a loro allocate non possono essere utilizzate da nessun altro processo
Programmazione concorrente
Lo stallo nei sistemi informatici

Situazione:
• due processi P1 e P2 che devono far uso sia di R1 che di
R2 per poter terminare il loro compito
• attesa circolare:
• il sistema operativo assegna R1 a P1 e R2 a P2
• P2 non potrà terminare giacché ha bisogno anche di R1
che è assegnata a P1
• P1 non potrà terminare giacché ha bisogno anche di R2
Grafo di Holt

che è assegnata a P2

• Situazione stallo
Programmazione concorrente
Perché si genera un deadlock

Condizioni di Coffman:
1. mutua esclusione
• le risorse vengono rilasciate solo a fine lavoro e una risorsa non
condivisibile deve essere utilizzata da un solo processo alla volta
2. impossibilità di prerilascio forzato
• Il sistema non può sottrarre forzatamente una risorsa al processo; una
risorsa può essere rilasciata volontariamente dal processo che la controlla
solo dopo che ha terminato di usarla
3. allocazione parziale e richieste bloccanti
• il processo non impegna, all’inizio del blocco critico, tutte le risorse di cui
avrà bisogno ma le richiederà (bloccandole) man mano che serviranno
(hold and wait)
4. attesa circolare
• Devono essere presenti almeno due processi, ciascuno dei quali in attesa di
una risorsa impegnata dall’altro.

Programmazione concorrente
Gestione dello stallo

Quattro diverse strategie:


1. Individuare e risolvere lo stallo
2. Evitare lo stallo
3. Prevenire lo stallo
4. Ignorare il problema

Programmazione concorrente
Individuazione dello stallo

Grafi di Holt
• Resource Allocation Graphs (RAG)
• Associano al processo le risorse di cui
necessitano

Programmazione concorrente
Individuazione dello stallo

Grafi di Holt

Programmazione concorrente
Individuazione dello stallo

Presenza di un ciclo

presenza di un deadlock.

Programmazione concorrente
Individuazione dello stallo

Presenza di un ciclo Presenza di un ciclo ma


risorsa con molteplicità > 1


presenza di un deadlock. presenza di un deadlock.

Programmazione concorrente
Individuazione dello stallo

Presenza di un ciclo Presenza di un ciclo ma


risorsa con molteplicità > 1


presenza di un deadlock. presenza di un deadlock.

Programmazione concorrente
Individuazione dello stallo

Presenza di un ciclo Presenza di un ciclo ma


risorsa con molteplicità > 1


presenza di un deadlock. presenza di un deadlock.

Programmazione concorrente
Individuare e risolvere lo stallo

Monitorare il sistema (grafi di Holt)


• Individuare lo stallo
Risolvere lo stallo
• Risoluzione manuale
• Intervento operatore
• Risoluzione automatica
• Meccanismi del S.O.

Programmazione concorrente
Individuare e risolvere lo stallo

Soluzioni
• terminazione dei processi
• metodo più semplice ma più drastico
• terminazione parziale (un processo per volta)
• non risolve?  terminazione totale
• scegliere quale processo far ripartire
• preemption
• prerilascio di una risorsa da parte di uno dei processi in stallo 
risorsa acquisita da altro processo che evolverà
• non idonea per tutte le risorse (es. stampanti)
• checkpoint/rollback
• salvataggio periodico su disco dello stato dei processi in certi istanti
(checkpoint)
• deadlock?  ripristino di uno/più processi a stato precedente
(rollback)

Programmazione concorrente
Individuare e risolvere lo stallo

Programmazione concorrente
Evitare lo stallo (avoidance)

• Analizzare in anticipo l’utilizzo delle risorse da parte dei processi


• Il processo causa stallo?  ritardare esecuzione processo
• Mantenere il sistema in uno stato sicuro

Programmazione concorrente
Algoritmo del banchiere

Proposto da Dijkstra nel 1965 per gestire l’avoidance

Programmazione concorrente
Algoritmo del banchiere

Soluzione
Clienti:
• possono chiedere un prestito una o più volte MA
• somma totale massima non superiore a quanto dichiarato in anticipo
Banchiere:
• cliente chiede prestito?  banca è in stato sicuro?  richiesta
accordata
• Banca in stato sicuro  i soldi rimanenti in cassa, dopo aver soddisfatto
la richiesta corrente, permettono di soddisfare almeno una successiva
richiesta massima da parte di un cliente che ancora non ne ha fatte

Programmazione concorrente
Algoritmo del banchiere - Esempi

Banchiere in stato sicuro


• Cassa sufficiente per soddisfare potenziali richieste di cliente A
• Con restituzione del fido di cliente A può soddisfare gli altri clienti

Programmazione concorrente
Algoritmo del banchiere - Esempi

• il cliente A non potrà più fare richiesta ma potrà solo restituire

• Il banchiere potrà soddisfare le future richieste di B e di C

Programmazione concorrente
Algoritmo del banchiere - Esempi

Banchiere in stato non sicuro


• non può più soddisfare l'eventuale richiesta di alcun cliente
• se tutti cominciano a chiedere un prestito e nessuno provvede a restituire, non
sarà in grado di soddisfare le richieste (stallo)
Programmazione concorrente
Algoritmo del banchiere

Traduzione informatica:
• ogni processo deve dichiarare il massimo numero di risorse che gli
sono necessarie
• a ogni richiesta di una nuova risorsa l’algoritmo deve verificare cosa
succede nel caso in cui venga soddisfatta questa richiesta
• la richiesta porta il sistema a uno stato sicuro o insicuro?
• si calcola la quantità di risorse rimanenti nel caso che questo
processo venga servito e si valuta se queste risorse possono soddisfare
la massima richiesta di almeno un processo che ancora deve essere
servito
• se sì l’allocazione viene accordata, altrimenti viene negata

Programmazione concorrente
Prevenire lo stallo

• Evitare il deadlock
• Eliminare una delle quattro condizioni che lo causano
• risorse seriali
• evitare la mutua esclusione permettendo la condivisione di
risorse
(Es. spool per gestire le code di stampa)
• hold & wait
• Allocazione totale
• escludere che un processo mantenga una risorsa anche
quando è in attesa di un’altra risorsa
• imporre che il processo richieda tutte le risorse all’inizio
• non sempre realizzabile
• Può provocare l’arresto di altri processi che
potrebbero evolvere (starvation)
Programmazione concorrente
Prevenire lo stallo

• Evitare il deadlock
• Preemption
• Forzare un processo a rilasciare le risorse in uso quando ne
richiede un’altra in quel momento indisponibile
• Il processo ripartirà quando potranno essergli assegnate tutte
le risorse precedenti e l’ultima richiesta
• Non sempre realizzabile (es. stampa in corso)
• attesa circolare
• Allocazione gerarchica
• Assegnazione di valori di priorità alle classi di risorse
• Ogni processo in ogni istante può allocare solo risorse di
priorità superiore a quelle che già possiede
• Per ottenere risorse con priorità inferiore deve rilasciare le
altre
• Assegnazione risorse ai processi secondo un ordine
prestabilito (a carico dell’amministratore del sistema)
• Introduce gravi rallentamenti
Programmazione concorrente
Ignorare il problema

Algoritmo “dello struzzo”


• ipotizzare che i deadlock non si possano mai
verificare
• precauzioni precedenti troppo costose

Programmazione concorrente
Il problema dei cinque filosofi

Proposto da Dijkstra nel 1965


Comportamento ripetitivo di ogni filosofo
• due fasi
I. Pensa lasciando le forchette sul tavolo
II. mangia avendo in ciascuna mano una forchetta
Considerazioni
• i filosofi non possono mangiare tutti insieme
• solo due filosofi alla volta possono nutrirsi
• due filosofi vicini di posto non possono mangiare contemporaneamente

Programmazione concorrente
Il problema dei cinque filosofi

Proposto da Dijkstra nel 1965


Comportamento ripetitivo di ogni filosofo
• due fasi
I. Pensa lasciando le forchette sul tavolo
II. mangia avendo in ciascuna mano una forchetta
Esempio di funzionamento
• il filosofo ha fame e smette di pensare
• prende la forchetta a sinistra del suo piatto;
• prende quella che è alla destra del suo piatto;
• mangia finché è sazio;
• rimette a posto, sul tavolo, le due forchette

Programmazione concorrente
Il problema dei cinque filosofi

Proposto da Dijkstra nel 1965


Comportamento ripetitivo di ogni filosofo
• due fasi
I. Pensa lasciando le forchette sul tavolo
II. mangia avendo in ciascuna mano una forchetta
Esempio di funzionamento
• il filosofo ha fame e smette di pensare
• prende la forchetta a sinistra del suo piatto;
• prende quella che è alla destra del suo piatto;
• mangia finché è sazio;
• rimette a posto, sul tavolo, le due forchette

SOLUZIONE: allocazione totale


ogni filosofo
Programmazione verifica se entrambe le forchette sono disponibili e solo in questo caso le acquisisce contemporaneamente,
concorrente
altrimenti rimane in attesa (condizione di hold and wait rimossa)
Criticità dei semafori

PRO CONTRO
• meccanismo molto potente per la • utilizzo spesso rischioso e
sincronizzazione dei processi difficoltoso
• primitive di “basso livello”
• il programmatore può causare
situazioni di deadlock
• esecuzioni erronee di difficile
verifica (race condition) per
errato/improprio uso delle
primitive

Programmazione concorrente
Soluzione

Monitor
• proposto da Hoare nel 1974 e da Brinch-Hansen nel 1975
• controllo esplicito delle regioni critiche mediante costrutti
linguistici “a più alto livello“
• è il compilatore che introduce il codice necessario al
controllo degli accessi

Programmazione concorrente
Monitor: definizione e generalità

• protegge i dati da accessi poco strutturati


• definisce la regione critica
• garantisce che i dati condivisi siano elaborati solo attraverso interfacce ben definite
• mette a disposizione sottoprogrammi che possono accedere a variabili e strutture
dati interne a esso
• un solo processo (o thread) alla volta può essere attivo entro il monitor e può quindi richiamare
queste procedure (in questo caso si dice che il processo è nel monitor)
• un thread che richiama una procedura di monitor quando un altro thread è già nel monitor, viene
sospeso e inserito in un’opportuna coda associata al monitor
• quando un thread all’interno del monitor si blocca, un altro thread deve poter accedere al monitor
Programmazione concorrente
Monitor: definizione e generalità

Programmazione concorrente
Uso dei monitor

Utilizzati per
• per il controllo degli accessi a una risorsa condivisa tra processi
concorrenti
• in base a politiche di gestione
• le variabili locali definiscono lo stato della risorsa associata al
monitor
• i processi possono aggiornare lo stato della risorsa mediante le
procedure entry
Usati come
• istanza di monitor
• oggetto di tipo monitor

Programmazione concorrente
Sincronizzazione mediante i monitor

Mutua esclusione da sola può non bastare


• Assegnazione della risorsa secondo due livelli di controllo
• primo livello: garantisce la mutua esclusione
• un solo processo alla volta può eseguire le entry (funzioni public)
• accesso alle variabili comuni del monitor regolato: se un processo
è dentro il monitor, gli altri vengono sospesi e messi nelle entry
queue
• secondo livello: controlla l’ordine con il quale i processi hanno
accesso alla risorsa
• in chiamata di procedura, se non viene verificata una condizione
logica che assicura l’ordinamento, il processo viene sospeso, viene
posto nella entry queue e il monitor liberato
• la sospensione del processo avviene utilizzando variabili di un
nuovo tipo, detto condition variables
• rappresentano la coda nella quale i processi si sospendono
Programmazione concorrente
Condition variables

• Sulle variabili di tipo condition si accede solamente mediante due procedure: wait() e signal()
• hanno come parametro la variabile sulla quale devono operare

• miaCondition è la variabile condition che deve essere testata: il processo che la esegue si sospende,
viene posto nella coda associata e libera il monitor

• miaCondition è la variabile condition da testare per liberare un processo in attesa: se la coda a esso
associata contiene almeno un processo, questo viene risvegliato e riprenderà l’esecuzione dentro il monitor,
a partire dall’istruzione seguente dalla wait() che lo aveva sospeso
• se non sono presenti processi in coda l’operazione non ha nessun effetto
• deve essere l’ultima istruzione eseguita dal processo all’interno del monitor; se viene risvegliato un
processo in attesa sullo stesso monitor questo lo troverà libero

Programmazione concorrente
dati condivisi che servono
alle entry per regolare
l’accesso alla risorsa:
- Stato della risorsa
- Condizione per gestione
coda attesa

equivale alla esecuzione di


un P() di un semaforo
MA ad alto livello

equivale alla esecuzione di


un V() di un semaforo
MA ad alto livello

Programmazione concorrente
Segmento di codice che “utilizza la risorsa”

Programmazione concorrente
Riepilogando

Programmazione concorrente

Potrebbero piacerti anche