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’operazione wait() 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 operazione signal() 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);
	}
}

Barriere