Università degli Studi di Bergamo Laboratorio di Sistemi Operativi

Transcript

Università degli Studi di Bergamo Laboratorio di Sistemi Operativi
Università degli Studi di Bergamo
Laboratorio di Sistemi Operativi a.a. 2015/16
LAB 6 - Esercitazione Monitor con lock e variabili condizione
1.
Il problema del barbiere dormiente: In un salone lavora un solo barbiere. Ci sono N=5 sedie per
accogliere i clienti in attesa ed una sedia di lavoro. Se non ci sono clienti, il barbiere si addormenta sulla
sedia di lavoro. Un cliente quando arriva deve svegliare il barbiere, se addormentato, o accomodarsi su
una delle sedie in attesa che finisca il taglio corrente. Se nessuna sedia è disponibile, il cliente preferisce
non aspettare e lascia il negozio.
Completare la classe BarberShop riportata nel riquadro sotto per coordinate il barbiere e i clienti
utilizzando come meccanismo di sincronizzazione i lock e le variabili condizione.
Il metodo startWorking() è invocato dal generico thread barbiere, mentre il metodo haircutRequest() è
eseguito da un generico thread cliente. Si completi il programma definendo le classi dei thread e la classe
contenente il metodo main per testare il programma.
import java.util.concurrent.locks.*;
class BarberShop {
//Oggetti condivisi:
static final int SEATS = 5; //Sedie disponibili per i clienti (=5)
int waiting; //Contatore dei clienti in attesa
final Lock lock = new ReentrantLock(); //Variabile di lock per la mutua esclusione
//Condition variables
final Condition …
<DA COMPLETARE>
public BarberShop(){ waiting = 0; //inizialmente, il salone è vuoto (senza clienti) }
//Metodo eseguito dal (thread) barbiere
public void startWorking() throws InterruptedException {
<DA COMPLETARE> }
//Metodo eseguito dal generico (thread) cliente
public void haircutRequest() throws InterruptedException { <DA COMPLETARE> }
//Simula il taglio dei capelli eseguito dal barbierepieno, il cliente se
public void performeHaircut(){
System.out.println("Barber is cutting hair");
try { Thread.currentThread().sleep(7500);}
catch (InterruptedException ex){ }
}
}
//Simula il comportamento del cliente durante il taglio
public void receiveHaircut(){
System.out.println("Customer " +
Thread.currentThread().getName() + " is getting his hair cut");
try { Thread.currentThread().sleep(10000);}
catch (InterruptedException ex){ }
}
2. Circolo enoculturale. In un circolo enoculturale, np persone appassionate di vino si riuniscono per una
degustazione. E’ presente una botte di vino pregiato di cui si desidera valutarne la qualità. La botte ha
nr=3 rubinetti e contiene inizialmente nl=50 litri di vino; di conseguenza possono bere solo nr
persone alla volta, sempre che la botte contenga ancora vino. Si supponga che ogni bevuta (da un singolo
rubinetto) faccia diminuire il vino in botte di una quantità q di litri variabile, ma inferiore a 2 litri; se la
quantità q è maggiore della disponibilità di vino presente nella botte, viene prelevata solo la quantità di
vino effettivamente presente (svuotando così la botte).
Nel riquadro sotto, è riportata la classe SynchronizedBarrel come parte di una soluzione in Java al
problema dato che usa come meccanismo di sincronizzazione i lock e le variabili condizione del package
java.util.concurrent. La classe SynchronizedBarrel contiene i metodi chooseDispenser e
drink invocati dal generico thread “bevitore” (la classe Boozer). Tali metodi consentano ad un
bevitore, rispettivamente, di accedere ad uno dei rubinetti e di prelevare una certa quantità di vino.
Il comportamento di un bevitore (vedi metodo run() nella classe Boozer) è il seguente: chiacchiera un
po’; poi decide di bere e si mette in attesa se non ci sono rubinetti liberi; una volta acquisito l’accesso
esclusivo ad un rubinetto decide una certa quantità casuale q di vino da bere e la preleva dalla botte;
infine, libera il rubinetto e ricomincia di nuovo. Qualora non ci fosse più vino, il bevitore termina la sua
esecuzione.
Completare la soluzione data, fornendo una definizione completa dei metodi chooseDispenser e
drink della classe SynchronizedBarrel.
//Classe del generico thread bevitore
public class Boozer extends Thread {
SynchronizedBarrel barrel; //riferimento all'oggetto sincronizzato botte
int id; //identificativo numerico del thread
}
public Boozer (SynchronizedBarrel barrel, int id){ //Costruttore
this.barrel=barrel;
this.id=id;
public void run(){
while (barrel.getLiters() > 0){ //Fintanto che la botte e' non vuota
//Chiacchiera un po' prima di mettersi in fila per bere
chitChat();
//Cerca di bere, cercando di accedere ad un rubinetto
barrel.chooseDispenser(id);
//Aspetta un tempo casuale al rubinetto, poi decide
//la quantità q di vino da prelevare (inferiore a 2 litri), e la preleva
try{
sleep( (int)( Math.random()*3000) );
} catch (InterruptedException e){}
double q= Math.random()*2;
barrel.drink(id, q);
}
}
}
public void chitChat(){
try{
//Aspetta un tempo casuale (max. 10 sec.)
sleep( (int)( Math.random()*10000) );
}catch (InterruptedException e){}
}
//Classe “monitor” dell’oggetto “botte”
import java.util.concurrent.locks.*;
public class SynchronizedBarrel {
private double liters; //numero corrente di litri nella botte
private int freeDispensers; // numero corrente di rubinetti liberi
final Lock lock = new ReentrantLock(); //lock per la mutua esclusione
final Condition dispensersCondition = lock.newCondition(); //Variabile condizione: c'è un rubinetto libero
SynchronizedBarrel (double nl, int nr){
liters = nl; //num. iniziale di litri di vino nella botte
freeDispensers = nr; //num. iniziale di rubinetti liberi nella botte
}
//Restituisce il num. corrente di litri di vino rimasti nella botte
public double getLiters(){
lock.lock();
//Sezione critica: lettura della variabile condivisa "litri rimasti"
try { return liters; }
finally { lock.unlock();}
}
}
public void chooseDispenser(int id){ <DA COMPLETARE> }
public void drink(int id, double q){ <DA COMPLETARE> }

Documenti analoghi

Slide - Università degli Studi di Bergamo

Slide - Università degli Studi di Bergamo // associated it with this lock object.! public void unlock();!

Dettagli

Lab 4: Locks, Condition Variables in Java

Lab 4: Locks, Condition Variables in Java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class CokeMachine { private static final int N = 50; //Capacità della macchinetta private int count ;...

Dettagli

Java, thread, synchronized, wait, notify

Java, thread, synchronized, wait, notify -  wait(): tale metodo rilascia il lock (mutua esclusione) sull'oggetto e sospende il thread che lo invoca in attesa di una notifica. -  notifyAll(): tale metodo risveglia tutti i thread sospesi su...

Dettagli

Processi e Thread

Processi e Thread alla volta possa eseguire un metodo definito come synchronized. Quando un metodo synchronized (es., nextNumber()) è invocato, l’oggetto corrispondente (cioè TakeANumber) è locked. Mutua esclusione:...

Dettagli