UniTO/anno2/YearI/FirstSem/MCAD/lesson9-25102017.md
Francesco Mecca 5e286062f8 MCAD 2019
2018-11-22 13:09:11 +01:00

4.9 KiB

Monitor

Un monitor e' una combinazione di ADT (abstract data type, tipo astratto) e mutua esclusione. (vedi slides per definizione)

  • I monitor sono strutture dati che implementano operazioni mutualmente esclusive.

Implementazione

monitor stack {
	.
	.
	public push()
	public pop()
	.
	.etc
}

Un monitor e' uno stack. (slides per implementazione classica)

Esempio

  • La definizione di monitor definisce un tipo alpha, secondo la definizione classica.
  • Il tipo definito puo' essere instanzializzato:
alpha x
  • Le operazioni generiche e pubbliche definite dal monitor sono chiamate con dot notation:
x.op_i()

Tutte le operazioni implementate dal monitor sono mutualmente esclusive, permettendo quindi una semplificazione e sicurezza maggiore nella scrittura di programmi concorrenti.

NOTA: Il runtime support del linguaggio, che opera a livello kernel, usa comunque primitive semaforiche. L'utilizzo e' pero' astratto dal costrutto monitor.

Variabili tipo condizione

Sono variabili che si possono usare solo all'interno del monitor. In genere, ogni condition e' implementata tramite una coda, di solito FIFO. Le procedure dei monitor agiscono sulle variabili condizione con le operazioni:

  • wait(cond) <- sospende il processo in ogni caso e lo introduce nella coda individuata da cond
  • signal(cond) <- rende attivo un processo in attesa nella coda individuata da cond

NOTA: wait e signal non sono equivalenti a P,V per i semafori, in quanto gestiscono automaticamente le code e non permettono di testare condizioni (if(cond)... va utilizzato prima di wait).

(slides per esempio) Le variabili condizione possono essere utilizzate anche come semafori privati (N variabili condizione per N processi).

Signal: realizzazione semantica

Signal non e' in grado di discriminare tra processi bloccati. Quindi bisogna discriminare, tra due processi, quale debba proseguire nella SC (processo svegliante o processo svegliato).

Dipende dall'implementazione del singolo linguaggio. Java, ad esempio, da la precedenza a un processo svegliante.

Questo implica l'utilizzo di un while loop per svegliare tutta la pool di processi in coda, che pero' non e' starvation free.

Java: Signal and continue

Quando un processo viene svegliato da un altro, viene rimesso in coda, mentre il processo svegliante puo' continuare nella SC. Il processo svegliato quindi potrebbe ritrovarsi alla fine della coda. Problema starvation svegliato

Signal and wait

Opposto del signal and continue: il processo svegliato prende il posto dello svegliante, e lo svegliante va in fondo alla coda. Problema starvation svegliante

Signal and urgent wait

Signal and wait, ma il processo svegliante acquisisce la prima posizione nella coda (urgent queue). Questo e' l'approccio piu' fair rispetto a tutti i processi.

(slides per esempio allocatore)

In una semantica SAUW, non ha senso utilizzare primitive signalAll, in quanto violano il principio della mutua esclusione.

Comparison: Monitor e Semafori

Qual'e' il piu' potente (inteso: che risolve la piu' vasta gamma di problemi) tra monitor e semafori?

  • Sono equivalenti, in quanto con i semafori e' possibile implementare i monitor, e con i monitor e' possibile implementare i semafori. Non sono quindi piu' potenti dei semafori, sono solo un'astrazione di essi.

(vedi slides per dimostrazione di realizzazione)

Operazioni aggiuntive su variabili condizione

  • wait(cond,p): wait con indicazione della priorita', che e' data come numerica, in ordine di solito decrescente. (priorita' 0 = massima). Il linguaggio implementa quindi una priority queue.

  • empty(cond): true se la coda e' vuota, false se ci sono processi in attesa

  • signalAll(cond): rende attivi tutti i processi in coda, ma si puo' utilizzare solo con signal and continue.

Esempi

Shortest-job-next: allocazione di risorse

monitor allocatore {
	bool occupata = false;
	condition non_occ;

	public void richiesta (int tempo) {
		if (occupata) {
			wait (non_occ, tempo);
			occupata = true;
		}
	}
}

(altri esempi su slides, disco a teste mobili, lettori / scrittori con monitor)

Monitor: Lettori / scrittori - Prova di correttezza

La prova di correttezza di un monitor si ottiene tramite gli invarianti di monitor, dimostrate valide per induzione:

  • sono vere al momento dell'inizializzazione del monitor
  • sono vere all'uscita di esecuzione della chiamata al monitor

L'invariante da dimostrare e' il seguente: siano:

  • R - numero di processi in lettura
  • W - numero di processi in scrittura
(R>0 => W=0) and (W <= 1) and (W = 1 => R = 0)
  • Facilmente dimostrabile e' il seguente gruppo di invarianti:
R = num_lett
W = num_scritt
R >= 0
W >= 0
Dimostrazione
  • All'inizio, l'invariante in tesi e' chiaramente vero.
  • Supposto vero all'inizio di ciascuna delle 4 procedure di monitor, e' vero anche alla fine.

(vedi slides per casi specifici)