1 lucidi delle esercitazioni di sistemi di elaborazione in rete università degli studi della...
TRANSCRIPT
1
Lucidi delle esercitazioni di
Sistemi di Elaborazione in Rete
Università degli Studi della Calabria
Corso di Laurea in Ingegneria Informatica
A.A. 2003/2004
2
Lettori-Scrittori con sincronizzazione Java (1)
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 */ }}
3
Lettori-Scrittori con sincronizzazione Java (2)
public synchronized int startRead()
{
while (dbWriting == true) {
try {
wait();
}
catch (InterruptedException e) { }
}
readerCount++;
if (readerCount == 1)
dbReading = true;
return readerCount;
}
4
Lettori-Scrittori con sincronizzazione Java (3)
public synchronized int endRead()
{
readerCount- -;
if (readerCount == 0)
{
dbReading=false;
notifyAll();
}
return readerCount;
}
5
Lettori-Scrittori con sincronizzazione Java (4)
public synchronized void startWrite()
{
while (dbReading == true || dbWriting == true) {
try { wait(); }
catch (InterruptedException e) { }
}
dbWriting = true;
}
public synchronized void endWrite()
{
dbWriting = false;
notifyAll();
}
6
Lettori-Scrittori con sincronizzazione Java (5)
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();
}}
}
7
Lettori-Scrittori con sincronizzazione Java (6)
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();
}}
}
8
Lettori-Scrittori con sincronizzazione Java (7)
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();
}
}
9
Blocchi sincronizzati (1)
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.
10
Blocchi sincronizzati (2)
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
}
11
I 5 filosofi con sincronizzazione Java (1)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;
02
43
1
0
12
3
4
12
I 5 filosofi con sincronizzazione Java (2)(senza deadlock)
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();
}}
13
I 5 filosofi con sincronizzazione Java (3)(senza deadlock e senza starvation)
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();
}}
14
I 5 filosofi con sincronizzazione Java (4)(I Threads Filosofo)
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*/
}}
}
15
I 5 filosofi con sincronizzazione Java (4)(Il main)
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();
}
}
16
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.
17
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 ( ) { … }
}
18
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;
}
19
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*/
20
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); }
21
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
}
}
22
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 (); } }}