1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della...

51
1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004

Transcript of 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della...

Page 1: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

1

Lucidi delle esercitazioni di

Sistemi di Elaborazione in Rete

Università degli Studi della Calabria

Corso di Laurea in Ingegneria Gestionale

A.A. 2003/2004

Page 2: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

2

Concetto di processo

Nei primi sistemi di calcolo era consentita l’esecuzione di un solo

programma alla volta. Tale programma aveva il completo controllo del

sistema e accesso a tutte le sue risorse.

Gli attuali sistemi di calcolo consentono, invece, che più programmi siano

caricati in memoria ed eseguiti concorrentemente. Essi sono detti

sistemi time-sharing o multitasking. In tali sistemi più programmi

vengono eseguiti dalla CPU, che commuta la loro esecuzione con una

frequenza tale da permettere agli utenti di interagire con ciascun

programma durante la sua esecuzione.

L’unità di lavoro dei moderni sistemi time-sharing è il processo.

Page 3: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

3

Definizione di processo

Un processo può essere definito come un programma in

esecuzione. Un processo esegue le proprie istruzioni in modo

sequenziale, ovvero in qualsiasi momento viene eseguita al massimo

un’istruzione del processo.

Un programma di per sé non è un processo: un programma è

un’entità passiva, come il contenuto di un file memorizzato su disco,

mentre un processo è una entità attiva, con un program counter che

specifica l’attività attuale (ovvero, quale sia la prossima l’istruzione da

eseguire) ed un insieme di risorse associate.

Due processi possono essere associati allo stesso programma, ma sono

da considerare due sequenze di esecuzione distinte.

Page 4: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

4

Processi indipendenti e cooperanti

I processi in esecuzione nel sistema operativo possono essere

indipendenti o cooperanti:

Un processo è indipendente se non può influire su altri processi nel

sistema o subirne l’influsso. Un processo che non condivida dati

temporanei o permanenti con altri processi è indipendente.

Un processo è cooperante se influenza o può essere influenzato da altri

processi in esecuzione nel sistema. Ovviamente, qualsiasi processo che

condivida dati con altri processi è un processo cooperante.

Page 5: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

5

Cooperazione tra processi

Ci sono diversi motivi per fornire un ambiente che consenta la

cooperazione tra processi:

Condivisione di informazioni. Consente a più utenti di condividere le

stesse informazioni (ad esempio un file).

Accelerazione del calcolo. Si divide un problema in sottoproblemi che

possono essere eseguiti in parallelo. Un’accelerazione di questo tipo è

ottenibile solo se il computer dispone di più elementi di elaborazione

(come più CPU o canali di I/O)

Modularità. Consente la realizzazione di un sistema modulare che divide

le funzioni in processi distinti.

Page 6: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

6

Thread

Un thread, anche detto lightweight process, è un flusso sequenziale di

esecuzione di istruzioni all’interno di un programma/processo.

In un programma si possono far partire più thread che sono eseguiti

concorrentemente. Nei computer a singola CPU la concorrenza viene

simulata con una politica di scheduling che alterna l'esecuzione dei

singoli thread.

Tutti i thread eseguono all’interno del contesto di esecuzione di un solo

processo, ovvero condividono le stesse variabili del programma.

Ciascun processo tradizionale, o heavyweight, ha invece il proprio

contesto di esecuzione.

Page 7: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

7

Thread in Java

Tutti i programmi Java comprendono almeno un thread. Anche un

programma costituito solo dal metodo main viene eseguito come un

singolo thread. Inoltre, Java fornisce strumenti che consentono di creare

e manipolare thread aggiuntivi nel programma

Esistono due modi per implementare thread in Java:

Definire una sottoclasse della classe Thread.

Definire una classe che implementa l’interfaccia Runnable. Questa

modalità è più flessibile, in quanto consente di definire un thread che è

sottoclasse di una classe diversa dalla classe Thread.

Page 8: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

8

Definire una sottoclasse della classe Thread

1. Si definisce una nuova classe che estende la classe Thread. La nuova

classe deve ridefinire il metodo run() della classe Thread.

2. Si crea un’istanza della sottoclasse tramite new.

3. Si chiama il metodo start() sull’istanza creata. Questo determina

l’invocazione del metodo run() dell’oggetto, e manda in esecuzione il

thread associato.

Page 9: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

9

Esempio di sottoclasse di Thread

class Saluti extends Thread {

public Saluti(String nome) { super(nome); }

public void run() { for (int i = 0; i < 10; i++) System.out.println("Ciao da "+getName()); }}

public class ThreadTest {

public static void main(String args[]) { Saluti t = new Saluti("Primo Thread"); t.start(); }}

Page 10: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

10

Definire una classe che implementa Runnable

1. Si definisce una nuova classe che implementa l’interfaccia Runnable. La nuova classe deve implementare il metodo run() dell’interfaccia Runnable.

2. Si crea un’istanza della classe tramite new.

3. Si crea un’istanza della classe Thread, passando al suo costruttore un riferimento all’istanza della nuova classe definita.

4. Si chiama il metodo start() sull’istanza della classe Thread creata, determinando l’invocazione del metodo run() dell’oggetto Runnable associato.

Page 11: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

11

Esempio di classe che implementa Runnable

class Saluti implements Runnable {

private String nome;

public Saluti(String nome) { this.nome = nome; }

public void run() { for (int i = 0; i < 10; i++) System.out.println("Ciao da "+nome); }}

public class RunnableTest {

public static void main(String args[]) { Saluti s = new Saluti("Secondo Thread"); Thread t = new Thread (s); t.start(); }}

Page 12: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

12

La classe Thread (1)

Costruttori principali:

Thread (): crea un nuovo oggetto Thread.

Thread (String name): crea un nuovo oggetto Thread con nome name.

Thread (Runnable target): crea un nuovo oggetto Thread a partire dall’oggetto target.

Thread (Runnable target, String name): crea un nuovo oggetto Thread con nome name a partire dall’oggetto target.

Metodi principali:

String getName(): restituisce il nome di questo Thread. void join() throws InterruptedException: attende fino a quando questo Thread non termina l’esecuzione del proprio metodo run.

Page 13: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

13

La classe Thread (2)

void join(long millis) throws InterruptedException: attende, per un tempo massimo di millis millisecondi, fino a quando questo Thread non termina l’esecuzione del proprio metodo run.

void run(): specifica le operazioni svolte dal Thread. Deve essere ridefinito dalla sottoclasse, altrimenti non effettua alcuna operazione. Se il Thread è stato costruito a partire da un oggetto Runnable, allora verrà invocato il metodo run di tale oggetto.

static void sleep(long millis) throws InterruptedException: determina l’interruzione dell’esecuzione del Thread corrente per un tempo di millis millisecondi.

void start(): fa partire l’esecuzione del Thread. Viene invocato il metodo run di questo Thread.

static void yield(): determina l’interruzione temporanea del Thread corrente, e consente ad altri Thread di essere eseguiti.

Page 14: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

14

La classe Thread (3)

static Thread currentThread(): restituisce un riferimento all’oggetto Thread attualmente in esecuzione.

void setPriority(int newPriority): cambia la priorità di questo Thread.

int getPriority(): restituisce la priorità di questo Thread.

Costanti della classe:

static final int MAX_PRIORITY: la massima priorità (pari a 10) che un Thread può avere.

static final int MIN_PRIORITY: la minima priorità (pari ad 1) che un Thread può avere.

static final int NORM_PRIORITY: la priorità (pari a 5) che viene assegnata di default ad un Thread.

Page 15: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

15

Ciclo di vita di un Thread

New: subito dopo l’istruzione new le variabili sono state allocate e inizializzate; il thread è in attesa di passare nello stato Runnable.

Runnable: il thread è in esecuzione o in coda di attesa per ottenere l’utilizzo della CPU.

Not Runnable: il thread non può essere messo in esecuzione dallo scheduler. Entra in questo stato quando è in attesa di operazioni di I/O, oppure dopo l’invocazione del metodo sleep(), o del metodo wait(), che verrà discusso in seguito.

Dead: al termine dell’esecuzione del suo metodo run().

New Runnable Not Runnable

Dead

start()

Il metodo run() termina

yield()

Page 16: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

16

Scheduling dei Thread

La Java Virtual Machine (JVM) è in grado di eseguire una molteplicità di

thread su una singola CPU:

lo scheduler della JVM sceglie il thread in stato Runnable con priorità più

alta;

se più thread in attesa di eseguire hanno uguale priorità, la scelta dello

scheduler avviene con una modalità ciclica (round-robin).

Il thread messo in esecuzione dallo scheduler viene interrotto se e solo se:

il metodo run termina l’esecuzione;

il thread esegue yield();

un thread con priorità più alta diventa Runnable;

il quanto di tempo assegnato si è esaurito (solo su sistemi che

supportano time-slicing).

Page 17: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

17

Un programma sequenziale (1)

class Printer { private int from; private int to;

public Printer (int from, int to) { this.from = from; this.to = to; }

public void print () { for (int i = from; i <= to; i++) System.out.print (i+"\t"); }}

public class PrinterApp { public static void main (String args[]) { Printer p1 = new Printer (1,10); Printer p2 = new Printer (11,20); p1.print(); p2.print(); System.out.println ("Fine"); }}

Page 18: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

18

Un programma sequenziale (2)

L’esecuzione di PrinterApp genera sempre il seguente output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Fine

I metodi:

p1.print()

p2.print()

System.out.println(“Fine”)

sono eseguiti in modo sequenziale.

Page 19: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

19

Un programma threaded (1)

class TPrinter extends Thread { private int from; private int to;

public TPrinter (int from, int to) { this.from = from; this.to = to; }

public void run () { for (int i = from; i <= to; i++) System.out.print (i+"\t"); }}

public class TPrinterApp { public static void main (String args[]) { TPrinter p1 = new TPrinter (1,10); TPrinter p2 = new TPrinter (11,20); p1.start(); p2.start(); System.out.println ("Fine"); }}

Page 20: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

20

Un programma threaded (2)

L’esecuzione di TPrinterApp potrebbe generare il seguente output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Fine

oppure:

Fine1 2 3 11 4 12 5 13 6 14 7 15 8 16 9 17 10 18 19 20

oppure:

1 2 11 12 3 4 Fine

5 13 14 6 7 15 8 16 17 9 18 19 20 10

e così via: non è possibile fare alcuna assunzione sulla velocità relativa di esecuzione dei thread. L’unica certezza è che le operazioni all’interno di un dato thread procedono in modo sequenziale.

Page 21: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

21

Imporre la sequenzialità

Per imporre la sequenzialità nell’esecuzione dei diversi thread si può fare uso del metodo join().public class TPrinterApp { public static void main (String args[]) { TPrinter p1 = new TPrinter (1,10); TPrinter p2 = new TPrinter (11,20); p1.start(); try { p1.join(); } catch (InterruptedException e) { System.out.println(e); } p2.start(); try { p2.join(); } catch (InterruptedException e) { System.out.println(e); } System.out.println ("Fine"); }}

public class PrinterApp { public static void main (String args[]) { Printer p1 = new Printer (1,10); Printer p2 = new Printer (11,20); p1.print(); p2.print(); System.out.println ("Fine"); }}

Page 22: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

22

Somma in concorrenza (1)

class Sommatore extends Thread { private int da; private int a; private int somma; public Sommatore (int da, int a) { this.da = da; this.a = a; } public int getSomma() { return somma; } public void run () { somma = 0; for (int i = da; i <= a; i++) somma += i; }}

Page 23: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

23

Somma in concorrenza (2)

public class Sommatoria { public static void main (String args[]) { int primo = 1; int ultimo = 100; int intermedio = (primo+ultimo)/2; Sommatore s1 = new Sommatore (primo,intermedio); Sommatore s2 = new Sommatore (intermedio+1,ultimo); s1.start(); s2.start(); try { s1.join(); s2.join(); } catch (InterruptedException e) { System.out.println (e); } System.out.println (s1.getSomma()+s2.getSomma()); }}

Page 24: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

24

Thread con attività ciclica (1)

Ciclo finito:

public void run (){ for (int i = 0; i < n; i++) { istruzioni }}

Ciclo infinito:

public void run (){ while (true) { istruzioni }}

Page 25: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

25

Thread con attività ciclica (2)

Ciclo con terminazione:

class myThread extends Thread { private boolean continua;

public myThread () { continua = true; }

public void termina () { continua = false; }

public void run () { while (continua) { istruzioni } }}

Page 26: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

26

Sincronizzazione dei Processi (1a parte)

Introduzione Il problema della sezione critica Soluzioni hardware per la sincronizzazione Semafori

Page 27: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

27

Introduzione

L’accesso concorrente a dati condivisi può portare all’inconsistenza dei dati.

Per garantire la consistenza dei dati sono necessari meccanismi per assicurare l’esecuzione ordinata dei processi cooperanti.

Page 28: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

28

Bounded-Buffer (1)

Dati condivisi

class item {

. . .

}

int BUFFER_SIZE = 10;

item buffer[] = new item [BUFFER_SIZE];

int in = 0;

int out = 0;

int counter = 0;

Page 29: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

29

Bounded-Buffer (2)

Processo produttore

item nextProduced;

while (true) {

nextProduced = new item (…);

while (counter == BUFFER_SIZE) ; /* do nothing */

buffer[in] = nextProduced;

in = (in + 1) % BUFFER_SIZE;

counter++;

}

Page 30: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

30

Bounded-Buffer (3)

Processo consumatore

item nextConsumed;

while (true) {

while (counter == 0) ; /* do nothing */

nextConsumed = buffer[out];

out = (out + 1) % BUFFER_SIZE;

counter--;

}

Page 31: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

31

Bounded-Buffer (4)

Le istruzioni:

counter++;counter--;

devono essere eseguite atomicamente.

Una operazione atomica è una operazione che si completa nella sua interezza senza interruzioni.

Page 32: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

32

Bounded-Buffer (5)

L’istruzione “counter++” può essere implementata in linguaggio macchina come:

register1 = counterregister1 = register1 + 1counter = register1

L’istruzione “counter--” può essere implementata come:

register2 = counterregister2 = register2 – 1counter = register2

Page 33: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

33

Bounded-Buffer (6)

Nel caso in cui il produttore ed il consumatore cercassero di aggiornare il buffer contemporaneamente, le istruzioni in linguaggio assembly potrebbero risultare interfogliate (interleaved).

L’interleaving dipende da come i due processi produttore e consumatore sono schedulati.

Page 34: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

34

Bounded-Buffer (7)

Si assuma che counter sia inizialmente 5. Un possibile interleaving delle istruzioni è:

producer: register1 = counter (register1 = 5)producer: register1 = register1 + 1 (register1 = 6)consumer: register2 = counter (register2 = 5)consumer: register2 = register2 – 1 (register2 = 4)producer: counter = register1 (counter = 6)consumer: counter = register2 (counter = 4)

Il valore di counter potrebbe essere o 4 o 6, mentre il valore corretto dovrebbe essere 5.

Page 35: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

35

Race Condition

Race condition: la situazione in cui più processi accedono e manipolano dati condivisi in modo concorrente. Il valore finale dei dati condivisi dipende da quale processo ha finito per ultimo.

Per eliminare le race condition, i processi concorrenti devono essere sincronizzati.

Page 36: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

36

Il problema della sezione critica

n processi che competono per usare dati condivisi.

Ciascun processo ha un segmento di codice, chiamato sezione critica, nel quale i dati condivisi sono acceduti.

Problema: garantire che quando un processo è in esecuzione nella sua sezione critica, nessun altro processo sia autorizzato ad eseguire la propria sezione critica.

Page 37: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

37

Soluzione al problema della sezione critica

Devono essere soddisfatti i seguenti requisiti:

1) Mutua esclusione. Se il processo Pi è in esecuzione nella propria sezione critica, nessuna altro processo può essere in esecuzione nella sua sezione critica.

2) Progresso. se nessun processo è in esecuzione nella propria sezione critica, allora soltanto i processi che cercano di entrare nella sezione critica partecipano alla decisione di chi entrerà davvero, e questa decisione deve avvenire in un tempo finito.

3) Attesa limitata. Deve esistere un limite nel numero di volte che altri processi sono autorizzati ad entrare nelle rispettive sezioni critiche dopo che un processo Pi ha fatto richiesta di entrare nella propria sezione critica e prima che quella richiesta sia soddisfatta.

Si assume che ciascun processo esegua a velocità non nulla Nessuna assunzione deve essere fatta sulla velocità relativa degli n

processi.

Page 38: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

38

Sezione critica: soluzioni

Soltanto 2 processi, P0 e P1

Struttura generale del processo Pi

while (true) {

entry section

sezione critica

exit section

sezione non critica

} I processi possono far uso di variabili condivise per

sincronizzare le loro azioni.

Page 39: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

39

Monitor (1) Costrutti di sicronizzazione di alto livello che consentono la

condivisione sicura di un tipo di dati astratto tra processi concorrenti.

monitor monitor-name{

dichiarazione di variabili condiviseprocedure entry P1 (…) {

. . .}procedure entry P2 (…) {

. . .} procedure entry Pn (…) {

. . .} monitor-name (…) {

codice di inizializzazione}

}

Page 40: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

40

Monitor (2)

Per consentire ad un processo di attendere all’interno di un monitor, si deve dichiarare una variabile condition:

condition x, y; Una variabile condition può essere manipolata solo attraverso le

operazioni wait e signal.

L’operazione

x.wait();sospende il processo che la invoca fino a quando un altro processo non invoca:

x.signal(); L’operazione x.signal risveglia esattamente un processo. Se

nessun processo è sospeso l’operazione di signal non ha effetto.

Page 41: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

41

Rappresentazione concettuale di un Monitor

Page 42: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

42

Monitor di Hoare e di Hansen

Supponiamo che un processo P esegua x.signal, ed esista un processo sospeso Q associato alla variabile condition x. Dopo la signal, occorre evitare che P e Q risultino contemporaneamente attivi all’interno del monitor:

Hansen: Q attende che P lasci il monitor o si metta in attesa su un’altra variabile condition.

Hoare: P attende che Q lasci il monitor o si metta in attesa su un’altra variabile condition. Questa soluzione è preferibile: infatti consentendo al processo P di continuare (soluzione di Hansen), la condizione logica attesa da Q può non valere più nel momento in cui Q viene ripreso.

Una soluzione di compromesso: P deve lasciare il monitor nel momento stesso dell’esecuzione dell’operazione signal, in quanto viene immediatamente ripreso il processo Q. Questo modello è meno potente di quello di Hoare, perchè un processo non può effettuare una signal più di una volta all’interno di una stessa procedura.

Page 43: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

43

Monitor in Java (1)

Tutti i thread che fanno parte di una determinata applicazione Java condividono lo stesso spazio di memoria, quindi è possibile che più thread accedano contemporaneamente allo stesso metodo o alla stessa sezione di codice di un oggetto.

Per evitare inconsistenze, e garantire meccanismi di mutua esclusione e sincronizzazione, Java supporta la definizione di oggetti “monitor”.

In Java, un monitor è l’istanza di una classe che definisce uno o più metodi synchronized. E’ possibile definire anche soltanto una sezione di codice (ovvero un blocco di istruzioni) come “synchronized”.

In Java ad ogni oggetto è automaticamente associato un “lock”: per accedere ad un metodo o a una sezione synchronized, un thread deve prima acquisire il lock dell’oggetto.

Il lock viene automaticamente rilasciato quando il thread esce dal metodo o dalla sezione synchronized, o se viene interrotto da un’eccezione. Un thread che non riesce ad acquisire un lock rimane sospeso sulla richiesta della risorsa fino a quando il lock non diventa disponibile.

Page 44: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

44

Monitor in Java (2)

Ad ogni oggetto contenente metodi o sezioni synchronized viene assegnata una sola variabile condition, quindi due thread non possono accedere contemporaneamente a due sezioni synchronized diverse di uno stesso oggetto.

L’esistenza di una sola variabile condition per ogni oggetto rende il modello Java meno espressivo di un vero monitor, che presuppone la possibilità di definire più sezioni critiche per uno stesso oggetto.

Page 45: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

45

Monitor in Java (3)

Ogni oggetto Java fornisce un insieme di metodi di sincronizzazione:

void wait() throws InterruptedException: blocca l’esecuzione del thread invocante, in attesa che un altro thread invochi i metodi notify() o notifyAll() sullo stesso oggetto monitor. Prima di bloccare la propria esecuzione il thread rilascia il lock.

void wait(long timeout) throws InterruptedException: è una variante di wait(). Blocca l’esecuzione del thread invocante, che viene risvegliato o dall’invocazione dei metodi notify() o notifyAll(), o quando sia trascorso un tempo pari a timeout millisecondi. L’invocazione di wait(0) equivale all’invocazione di wait().

void notify(): risveglia un unico thread in attesa sull’oggetto monitor corrente. Se più thread sono in attesa, la scelta avviene in maniera arbitraria, dipendente dall’implementazione della Java Virtual Machine. Il thread risvegliato compete con ogni altro thread, come di norma, per ottenere la risorsa condivisa.

void notifyAll(): esattamente come notify(), ma risveglia tutti i thread in attesa sull’oggetto corrente. È necessario tutte le volte in cui più thread possano essere sospesi su differenti sezioni critiche dello stesso oggetto (in quanto esiste una unica coda d’attesa).

Page 46: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

46

Bounded Buffer con sincronizzazione Java (1)public class BoundedBuffer{ private int buffer[]; private int in=0, out=0, count=0, dim;

public BoundedBuffer (int dim) { this.dim=dim; buffer=new int[dim]; }

public synchronized int get () { /* lucidi seguenti */ }

public synchronized void put (int item) { /* lucidi seguenti */ }}

Page 47: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

47

Bounded Buffer con sincronizzazione Java (2)

public synchronized int get (){ while (count==0) { try { wait(); } catch (InterruptedException e) { } } int item = buffer[out]; out=(out+1)%dim; count--; notifyAll(); return item;}

Page 48: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

48

Bounded Buffer con sincronizzazione Java (3)

public synchronized void put (int item){ while (count==dim) { try { wait(); } catch (InterruptedException e) { } } buffer[in] = item; in=(in+1)%dim; count++; notifyAll();}

Page 49: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

49

Bounded Buffer con sincronizzazione Java (4)public class Consumer extends Thread{ private BoundedBuffer buffer; private int id; public Consumer (BoundedBuffer buffer, int id) { this.buffer = buffer; this.id = id; } public void run () { for (int i=0; i<10; i++) { int value = buffer.get(); System.out.println ("Consumer #"+id+" ha estratto "+value); } }}

Page 50: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

50

Bounded Buffer con sincronizzazione Java (5)public class Producer extends Thread{ private BoundedBuffer buffer; private int id; public Producer (BoundedBuffer buffer, int id) { this.buffer = buffer; this.id = id; } public void run () { for (int i=0; i<10; i++) { buffer.put(i); System.out.println ("Producer #"+id+" ha inserito "+i); } }}

Page 51: 1 Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete Università degli Studi della Calabria Corso di Laurea in Ingegneria Gestionale A.A. 2003/2004.

51

Bounded Buffer con sincronizzazione Java (6)public class BBTest{ public static void main (String args[]) { BoundedBuffer bb = new BoundedBuffer (10); Producer pv[] = new Producer [5]; for (int i = 0; i < 5; i++) { pv[i] = new Producer (bb,i); pv[i].start(); }

Consumer cv[] = new Consumer [9]; for (int i = 0; i < 9; i++) { cv[i] = new Consumer (bb,i); cv[i].start(); } }}