Università degli Studi di Bergamo Laboratorio di Sistemi Operativi
Transcript
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
// associated it with this lock object.!
public void unlock();!
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 ;...
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...
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:...