230 likes | 608 Views
Università degli Studi della Calabria Corso di Laurea in Ingegneria Informatica. Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete. A.A. 2003/2004. public class Database { private int readerCount; private boolean dbReading; private boolean dbWriting;
E N D
Università degli Studi della CalabriaCorso di Laurea in Ingegneria Informatica Lucidi delle esercitazioni di Sistemi di Elaborazione in Rete A.A. 2003/2004
public class Database { private int readerCount; private boolean dbReading; private boolean dbWriting; public Database() { readerCount = 0; dbReading = false; dbWriting = false; } public synchronized int startRead() { /* lucidi seguenti*/ } public synchronized int endRead() { /* lucidi seguenti */ } public synchronized void startWrite() { /* lucidi seguenti */ } public synchronized void endWrite() { /* lucidi seguenti */ } } Lettori-Scrittori con sincronizzazione Java (1)
public synchronized int startRead() { while (dbWriting == true) { try { wait(); } catch (InterruptedException e) { } } readerCount++; if (readerCount == 1) dbReading = true; return readerCount; } Lettori-Scrittori con sincronizzazione Java (2)
public synchronized int endRead() { readerCount- -; if (readerCount == 0) { dbReading=false; notifyAll(); } return readerCount; } Lettori-Scrittori con sincronizzazione Java (3)
public synchronized void startWrite() { while (dbReading == true || dbWriting == true) { try { wait(); } catch (InterruptedException e) { } } dbWriting = true; } public synchronized void endWrite() { dbWriting = false; notifyAll(); } Lettori-Scrittori con sincronizzazione Java (4)
public class Readers extends Thread { Database db; int id; public Readers(Database db,int id){ this.db=db; this.id=id; } public void run(){ while (true){ db.startRead(); db.endRead(); } } } Lettori-Scrittori con sincronizzazione Java (5)
public class Writers extends Thread { Database db; int id; public Writers(Database db,int id){ this.db=db; this.id=id; } public void run(){ while (true){ db.startWrite(); db.endWrite(); } } } Lettori-Scrittori con sincronizzazione Java (6)
public class TestRW { public static void main(String [ ] args){ Database db=new Database(); for (int i=0;i<10;i++){ (new Readers(db,i)).start(); (new Writers(db,i)).start(); } } Lettori-Scrittori con sincronizzazione Java (7)
Anche blocchi di codice, oltre che interi metodi, possono essere dichiarati synchronized. Ciò consente di associare un lock la cui durata è tipicamente inferiore a quella di un intero metodo synchronized. Blocchi sincronizzati (1)
public void syncronized F() { // sezione non critica (p.es.: inizializzazione di variabili locali) // sezione critica // sezione non critica } public void F() { // sezione non critica synchronized (this) { // sezione critica } // sezione non critica } Blocchi sincronizzati (2)
Supponiamo esista un tavolo con 5 piatti, 5 posti a tavola, 5 forchette ed al centro un’insalatiera di spaghetti. I filosofi seduti intorno al tavolo sanno fare solo due cose: mangiare e pensare. Il problema è che, siccome si tratta di spaghetti, il generico filosofo per servirsi ha bisogno di entrambe le forchette (quella alla sua DS e quella alla sua SN). Poi per mangare gliene serve solo una. La forchetta a SN dell’i-simo filosofo è: i; La forchetta a DS dell’i-sima filosofo è: (i+1)%5; I 5 filosofi con sincronizzazione Java (1) 1 2 1 2 0 0 3 3 4 4
Public class 5Filosofi { private boolean fork[ ]={true,true,true,true,true}; public synchronized void getForks(int i) { while(!fork[i] || !fork[(i+1)%5]) try{wait(); }catch(InterruptedException e){ } fork[i]=false; fork[(i+1)%5]=false; notifyAll(); /*eventuale*/ } public synchronized void putForks(int i) { fork[i]=true; fork[(i+1)%5]=true; notifyAll(); } } I 5 filosofi con sincronizzazione Java (2)(senza deadlock)
Public class 5Filosofi { private boolean fork[ ]={true,true,true,true,true}; int cont[]={0,0,0,0,0}; public synchronized void getForks(int i) { while(!fork[i] || !fork[(i+1)%5] || (cont[i]>cont[(i+1)%5)] || (cont[i]>cont[(i+4)%5]) try{wait(); }catch(InterruptedException e){ } fork[i]=false; fork[(i+1)%5]=false; notifyAll(); /*eventuale*/ } public synchronized void putForks(int i) { fork[i]=true; fork[(i+1)%5]=true; cont[i]++; notifyAll(); } } I 5 filosofi con sincronizzazione Java (3)(senza deadlock e senza starvation)
public class Filosofo extends Thread { int id; 5Filosofi cf; public Filosofo(int id, String nome, 5Filosofi cf) { super(nome); this.id=id; this.cf=cf; } public void run() { for(; ;){ cf.getForks(id); System.out.println(“Il filosofo”+id+” mangia”); try{ sleep((int)(Math.random()*5000)); catch(InterruptedException e){ } /*il filosofo sta mangiando*/ cf.putForks(id); try{ sleep((int)(Math.random()*5000));} catch(InterruptedException e){ } /*il filosofo sta pensando*/ } } } I 5 filosofi con sincronizzazione Java (4)(I Threads Filosofo)
public class Test5Filosofi { public static void main(String [] args){ 5Filosofi gestore=new 5Filosofi(); for (int i=0;i<5;i++) new Filosofo(i,”Filosofo# “+i, gestore).start(); } } I 5 filosofi con sincronizzazione Java (4)(Il main)
Il problema dello Sleeping Barber • E’ dato un salone di barbiere, avente un certo numero di posti d’attesa ed un’unica poltrona di lavoro. Nel salone lavora un solo barbiere, il quale è solito addormentarsi sulla poltrona di lavoro in assenza di clienti. • Arrivando nel salone, un cliente può trovare le seguenti situazioni: • Il barbiere dorme sulla poltrona di lavoro. Il cliente sveglia il barbiere e si accomoda sulla poltrona di lavoro, quindi il barbiere lo serve. • Il barbiere sta servendo un altro cliente: se ci sono posti d’attesa liberi, il cliente attende, altrimenti se ne va. • Scrivere in Java un programma che risolva tale problema, simulando l’attività dei diversi soggetti (il Salone, il Barbiere, i Clienti) ed evidenziandone su video lo stato. • L’implementazione della soluzione deve far uso delle opportune primitive di sincronizzazione e mutua esclusione.
Salone (1) public class Salone implements Runnable { int sedie,posti; Thread barbiere=null; boolean dorme,cliente; boolean fineAttesa; public Salone(int sedie){ this.sedie=sedie; posti=sedie; dorme=true; cliente=false; fineAttesa=false; barbiere=new Thread(this); barbiere.start(); } public synchronized boolean richiesta ( ) { … } public void run ( ) { … } }
Salone: richiesta (2) public synchronized boolean richiesta( ) { if (posti==0) return false; if ( (posti<sedie) || (!dorme)){ posti--; while(true) { try {wait();}catch(InterruptedException e){ } if (fineAttesa){ fineAttesa=false; notifyAll(); break; } } cliente=true; } else{ dorme=false; cliente=true; notify(); } while (cliente) try{wait();}catch(InterruptedException e){} return true; }
Salone: run (3) public void run ( ) { while (true){ synchronized(this) { if (!cliente) { if (posti==sedie) { dorme=true; while(dorme) try{wait();}catch(InterruptedException e){ } } else{posti++;fineAttesa=true; notify(); while (fineAttesa) try{wait();}catch(Interrupted…){} } /*fine synchronized*/ try{ Thread.sleep((int)(Math.random*1000));}catch(…){}; synchronized (this){ cliente=false; notifyAll(); } } } }/*fine Salone*/
Cliente (1) class Cliente extends Thread { private Salone salone; private int id; public Cliente (Salone salone, int id) { this.salone = salone; this.id = id; } public void run () { while (true) { boolean servito=salone.richiesta(); if (servito) { int tempoDiRicrescita = (int)((Math.random()*3000)); System.out.println ("Il cliente "+id+" attende la ricrescita dei capelli. "+"Tempo di ricrescita = "+tempoDiRicrescita); try { sleep (tempoDiRicrescita); } catch (InterruptedException e) { System.out.println (e); }
Cliente (2) else{ System.out.println(“Il cliente+ id+”trova tutto pieno e va via…”); int tempoDiRiprovo= (int)((Math.random()*1000)); try { sleep (tempoDiRiprovo); } catch (InterruptedException e) { System.out.println (e); } } } // while } }
Il problema dello Sleeping Barber public class SleepingBarber { public static void main (String args[]) { int postiDiAttesa=5; Salone s = new Salone (postiDiAttesa); /*il barbiere è già attivo*/ for (int i = 1; i <= 10; i++) { Cliente c = new Cliente (s, i); c.start (); } } }