Caricare documenti e articoli online 
INFtub.com è un sito progettato per cercare i documenti in vari tipi di file e il caricamento di articoli online.


 
Non ricordi la password?  ››  Iscriviti gratis
 

IL COSTRUTTO 'MONITOR'

informatica



IL COSTRUTTO 'MONITOR'


Un OGGETTO è caratterizzato dal possedere:

- una struttura dati;

- dei metodi per accedere a tale struttura.

L'oggetto inoltre si trova volta per volta in un determinato STATO. Lo stato iniziale viene assegnato tramite una procedura di 323i86d inizializzazione; l'oggetto poi transita di stato in stato per mezzo dei summenzionati metodi di accesso alla struttura dati.


Il Pascal Concorrente permette di definire un oggetto tramite il costrutto CLASS. Anche il Pascal standard, a partire dalla versione 6.0, permette di definire oggetti mediante il costrutto Unit, ma nel contesto di una programmazione rigidamente sequenziale (il Pascal standard non è difatti un linguaggio concorrente).




Il costrutto MONITOR rappresenta un'estensione del concetto di oggetto. I 'metodi' di accesso alla struttura dati, detti ENTRY, vengono eseguiti in mutua esclusione tra i vari processi che la richiedono. (Di un oggetto possono far parte inoltre altre procedure, di livello più basso rispetto alle entry, e che vengono da queste richiamate per svolgere determinate funzioni).

Questo costrutto dunque permette di incapsulare in un unico modulo una struttura dati comune a più processi e le procedure che agiscono su di essa. Nei fatti, MONITOR costituisce un ulteriore modo di creare un gestore di risorsa. Infatti, un gestore di risorsa è per definizione una struttura dati corredata di metodi di accesso che devono essere eseguiti in mutua esclusione tra più processi. Anche MONITOR consente di inizializzare la struttura dati al momento della sua istanziazione.


Ora presentiamo il costrutto MONITOR a livello di linguaggio di programmazione concorrente.


Type < nome del tipo > = MONITOR ;

< dichiarazione di variabili locali > ; /* rappresentano le variabili condivise

tra vari processi, il cui accesso deve essere regolamentato */


Procedure entry < nome > (...) ;

begin ... end ;



Procedure entry < nome > (...) ;

begin ... end ;


Procedure < nome > (...) ;

begin ... end ;



Procedure < nome > (...) ;

begin ... end ;


begin

< inizializzazione delle variabili locali >

end ;



Come si vede il costrutto MONITOR si presenta, da un punto di vista sintattico, identico al costrutto CLASS, e questo è naturale in quanto entrambi sono stati ideati per definire degli oggetti. Ci sono tuttavia delle differenze molto significative:

1) MONITOR permette di condividere l'oggetto tra più processi;

2) non appena un processo invoca una procedura ENTRY e riesce ad accedere al monitor, il compilatore deve garantire che questo sia l'unico processo attivo all'interno del monitor. Quindi se altri processi invocano una ENTRY del medesimo monitor vengono sospesi, e solo quando il processo che si trova nel monitor ne esce uno di essi può entrarvi. Tutto ciò comunque avviene in maniera trasparente rispetto al programmatore che usa il costrutto MONITOR;

3) se capita che un processo penetra nel monitor e, dopo aver valutato una condizione, si 'accorge' di non potere più andare avanti, il costrutto deve fare in modo che il processo ne esca e che vengano create le condizioni affinché altri possano entrare. Questa è una generalizzazione dell'istruzione AWAIT cui si è accennato nel denunciare gli inconvenienti della Regione critica condizionale (in effetti il costrutto MONITOR, essendo il più generale visto fin qui, deve necessariamente includere tutti i costrutti già studiati).


Cerchiamo ora di capire come viene ad essere implementata a livello di linguaggio quest'ultima prerogativa.

Si definisce una variabile appartenente ad un tipo 'speciale', nel senso che può essere utilizzato soltanto in quei linguaggi nei quali è previsto il costrutto MONITOR. Si tratta del tipo CONDITION:


Var x : CONDITION;


Su di una variabile di tipo condition possono essere fatte due operazioni, indicate con i nomi di x.wait e x.signal, che però non vanno confuse con le omonime primitive funzionanti sui semafori.

Effettuare una x.wait significa esprimere la volontà incondizionata di sospendersi. Ad ogni variabile di tipo condition è associata una coda, e un processo che esegue un'operazione di wait su di una variabile del genere si va a mettere deliberatamente in quella coda, liberando il monitor. A questo punto, solo l'esecuzione di una x.signal da parte di un altro processo potrà risvegliarlo. La x.signal non ha invece alcun effetto se viene eseguita quando non vi è alcun processo in attesa sulla variabile condition x.

Un processo si mette in attesa (mediante l'esecuzione di un x.signal) perché è risultata falsa una condizione di sincronizzazione dipendente sia dalle variabili locali del monitor che dalle variabili proprie del processo.

Poiché, d'altronde, la x.signal può essere eseguita solamente dall'interno di un monitor, sembrerebbe che in seguito a tale istruzione nel monitor debbano ripartire due processi contemporaneamente: P, che ha eseguito la x.signal, e Q, che ne è stato appena risvegliato. Ciò sarebbe contrario a quanto è stato detto poco fa nel punto 2). In realtà, il meccanismo garantisce che in quest'eventualità uno dei due processi viene automaticamente sospeso. Per la precisione, è il processo sbloccante ad essere arrestato. Questo perché, se fosse consentito invece a P di proseguire, quest'ultimo potrebbe modificare ancora una volta la condizione di sincronizzazione e compromettere una successiva ripartenza di Q.

Dunque, in seguito alla x.signal P viene sospeso e Q riparte. Tuttavia, il meccanismo fornisce anche una 'assicurazione' a Q, nel senso che non appena P uscirà del monitor (per averne completato l'uso, o perché di nuovo costretto a sospendersi) sarà Q a rientrarvi, e non altri processi che nel frattempo potrebbero essersi messi in attesa. Tutte queste operazioni vengono garantite in modo automatico dal costrutto MONITOR.

Il monitor resterà libero quando P e Q avranno entrambi terminato, o se si troveranno entrambi in uno stato di wait, o se uno dei due avrà terminato e l'altro si troverà in uno stato wait. È compito del programmatore garantire che quando il monitor viene liberato esso abbia una struttura dati consistente.


Facciamo ora un esempio pratico: la realizzazione di una regione critica mediante il costrutto MONITOR. Specificamente, mediante le procedure Richiesta e Rilascio i processi rispettivamente richiedono l'uso esclusivo di una risorsa e la rilasciano. Si ha:


type allocatore : MONITOR ;

var occupato: boolean ;

libero: condition


procedure Richiesta ;

begin

if occupato then libero.wait ;

occupato : = true ;

end ;


procedure Rilascio ;

begin

occupato : = false ;

libero.signal ;

end ;


begin

occupato : = false ;

end ;


Indicando ora con alloc una variabile di tipo allocatore (le variabili monitor vengono chiamate anche istanze):


Var alloc : allocatore ;


un generico processo effettuerà la richiesta e il successivo rilascio della risorsa secondo il semplice schema:


Process P;

begin

...

alloc.Richiesta ;

< uso della risorsa > ;

alloc.Rilascio ;

...

end ;


Si comprende facilmente che questo esempio rappresenta la realizzazione di un semaforo binario. La procedura richiesta ne rappresenta la primitiva WAIT, e rilascio rappresenta la SIGNAL. La coda del semaforo coincide con la coda della variabile libero di tipo condition, mentre la variabile semaforo è rappresentata dalla booleana occupato.

La condizione di sincronizzazione che, se non verificata, provoca l'autosospensione di un processo richiedente è occupato = false.

Questo esempio illustra le reali differenze fra le primitive wait & signal operanti sui semafori e le omonime utilizzate all'interno dei monitor. In questo secondo caso, wait e signal hanno unicamente lo scopo di sospendere e riattivare i processi, e infatti il test sullo stato della risorsa controllata viene realizzato al di fuori di tali primitive



REALIZZAZIONE DEL COSTRUTTO MONITOR


La condizione di mutua esclusione tra le procedure può essere ottenuta associando ad ogni istanza del monitor un semaforo mutex inizializzato ad 1. Dunque la richiesta da parte di un processo di usare una procedura del monitor equivale all'esecuzione di una WAIT (mutex).

Quando un processo sospeso viene riattivato, deve essere sempre sospeso il processo che ha eseguito la signal sulla variabile condizione. Per ottenere questo risultato, si associa ad ogni monitor un secondo semaforo urgent, inizializzato a 0, sul quale il processo 'sbloccante' si arresta tramite una WAIT (urgent). Prima di abbandonare il monitor è necessario verificare che nessun processo sia in coda a tale semaforo.

Indicando con urgentcount un contatore, inizializzato a 0, del numero di processi sospesi sul semaforo urgent, l'uscita da una procedura del monitor viene codificata così:


if urgentcount > 0 then SIGNAL (urgent) else SIGNAL (mutex) ;




Veniamo adesso alla variabile di tipo condition (la chiamiamo cond). Ad essa associamo un semaforo condsem, inizializzato a 0, sul quale un processo può sospendersi tramite una WAIT (condsem), e un contatore condcount, inizializzato a 0, per tener conto dei processi sospesi sul semaforo condsem.


L'operazione COND.WAIT può essere realizzata così:


condcount : = condcount + 1

if urgentcount > 0 then SIGNAL (urgent) else SIGNAL (mutex) ;

WAIT (condsem) ;

condcount : = condcount - 1 ;


Mentre per l'operazione COND.SIGNAL è:


urgentcount : = urgentcount + 1 ;

if condcount > 0 then

begin

SIGNAL (condsem) ;

WAIT (urgent) ;

end ;

urgentcount : = urgentcount - 1 ;


Imponiamo ora una condizione: cioè che l'operazione COND.SIGNAL sia eseguita sempre come ultima operazione di ogni procedura. Questa non è una condizione eccessivamente restrittiva, e ha il vantaggio di semplificare le cose; infatti non è necessario introdurre il semaforo urgent e il contatore urgentcount. La COND.WAIT diviene:


condcount : = condcount + 1 ;

SIGNAL (mutex) ;

WAIT (condsem) ;

condcount : = condcount - 1 ;


E la COND.SIGNAL:


if condcount > 0 then SIGNAL (condsem) else SIGNAL (mutex) ;



In conclusione, possiamo dire che il costrutto MONITOR è un'astrazione che permette al programmatore di concentrarsi sulle politiche di gestione delle risorse senza andare ad impantanarsi nelle code e nei meccanismi semaforici di basso livello. Anche se si usa un linguaggio che non mette a disposizione il costrutto MONITOR, conviene ragionare in termini di tale costrutto e successivamente effettuare una traduzione. Del resto è consigliabile creare una volta per tutte le necessarie procedure (COND.WAIT etc.), in modo che quando queste si renderanno necessarie sarà sufficiente richiamarle.

LEZIONE N° 11 (DE CARLINI) - 21/3/97




La volta scorsa abbiamo introdotto il costrutto MONITOR e ne abbiamo visto la traduzione in termini di semafori e una semplice applicazione.


I processi che si bloccano su di una variabile di tipi condition vengono gestiti secondo l'usuale disciplina FIFO. Quindi l'esecuzione di una istruzione del tipo x.signal sortisce il risveglio del processo che è in attesa da più tempo. In alcuni casi tale politica, che impedisce il problema dell'attesa infinita, risulta però inadeguata, poiché sarebbe preferibile usufruire di una differente gestione prioritaria dei processi. Questo può essere ottenuto in due modi:

- mediante una signal che invece di risvegliare il processo in testa alla coda, risveglia il processo che, secondo i criteri che sono stati fissati, risulta avere la maggiore priorità.

- mediante una wait condizionale, che riceve in ingresso un parametro intero p, di cui essa si serve per inserire il processo bloccato al posto p-esimo della coda. In questo modo la signal classica sbloccherebbe automaticamente il processo più prioritario.

Nel seguito supporremo di usare questo tipo di wait, accettando il rischio (comunque molto improbabile) di provocare un fenomeno di attesa infinita.


Esaminiamo un ulteriore, interessante problema che può essere risolto agevolmente mediante i monitor.







Privacy




Articolo informazione


Hits: 2636
Apprezzato: scheda appunto

Commentare questo articolo:

Non sei registrato
Devi essere registrato per commentare

ISCRIVITI



Copiare il codice

nella pagina web del tuo sito.


Copyright InfTub.com 2024