Un monitor è una collezione di procedure e variabili raggruppate in un unico modulo (o pacchetto).
I processi possono invocare le procedure all’interno del monitor per accedere alle sue strutture dati e variabili, ma non possono accedere direttamente alle sue strutture dati e variabili da procedure dichiarate all’esterno del monitor.
Quindi quando un processo chiama una procedura del monitor, si controlla prima se un altro processo non è attivo nel monitor, e in caso affermativo il processo chiamante viene sospeso, finché l’altro processo non lascia il monitor.
Il monitor è un costrutto del linguaggio di programmazione, così il compilatore gestisce la mutua esclusione dei monitor, riducendo la probabilità di errori dal parte del programmatore.
Un limite dei monitor è che dipendono molto dal linguaggio di programmazione, infatti i linguaggi C e Pascal non li supportano nativamente (eccezione Java con synchronized).
Variabili di condizione, wait e signal
I monitor utilizzano le variabili di condizione e due operazioni speciali che sono wait() e signal():
wait(): quando una procedura all’interno del monitor (es. produttore) scopre che non può continuare a causa di una condizione (es. buffer pieno), esegue un’operazionewait()su una variabile di condizione (es. pieno) e blocca il processo. Il processo bloccato esce dal monitor e si mette in attesa.signal(): un altro processo (es. consumatore) che modifica lo stato del monitor e rimuove la condizione bloccante (es. rende disponibile uno slot del buffer) può risvegliare il partner in attesa inviando una operazionesignal()sulla variabile di condizione (es. pieno).
Un modello di producer-consumer utilizzando i monitor è il seguente :
monitor ProdCons{
condition full, empty;
int count = 0;
void insert(int item){
if (count == N) wait(full); // buffer pieno aspetta
insert_item(item);
count++;
if (count == 1) signal(empty);
}
void get(int *item){
if(count == 0) wait(empty); // buffer vuoto aspetta
*item = get_item();
count--;
if(count == N-1) signal(full);
}
}che poi può essere utilizzato dai thread producer-consumer :
void producer(){
int item;
while(TRUE){
item = produce_item();
ProdCons.insert(item); // accede al monitor ProdCons
}
}
void consumer(){
int item;
while(TRUE){
ProdCons.get(&item); // accede al monitor
consume_item(item);
}
}