Officina Ferrari
Ci sono nGomme
gommisti che montano gomme sulle auto. I gommisti devono attendere
l’arrivo delle gomme su 2 nastri. Ogni gommista ha un id. Se l’id è pari attende
le gomme dal nastro 0 (destro) se l’id è dispari dal nastro sinistro (1).
i gommisti non si scontrano tra loro (questa sincronizzazione è già realizzata)
Si devono realizzare le seguenti sincronizzazioni
- i gommisti attendono la gomma sul nastro (
attendiGomma
) - i gommisti notificano l’avvenuto prelievo della gomma (
prelevataGomma
) - i nastri si fermano finché uno dei gommisti non preleva la gomma (
gommaFineNastro
) - i gommisti attendono le auto (
attendiAuto
) - i gommisti notificano l’avvenuto montaggio (
gommaMontata
) - le auto attendono il montaggio di tutte le gomme (
attendiMontaggioGomme
)
Le auto si comportano come segue:
while(true) {
// Porta le macchine senza gomme
// Attende il montaggio delle gomme
officina.attendiMontaggioGomme();
// Porta via le macchine con le gomme
}
I gommisti si comportano come segue:
while(true) {
// il gommista si sposta fino al nastro delle gomme
// il gommista attende la gomma
officina.attendiGomma(id);
// il gommista rimuove la gomma dal nastro
// il gommista notifica che ha prelevato la gomma
officina.prelevataGomma(id);
// il gommista si sposta fino all'auto per montare la gomma
// il gommmista attende l'auto
officina.attendiAuto(id);
// il gommista notifica il montaggio della gomma
officina.gommaMontata(id);
}
I nastri delle gomme si comportano come segue:
while(true) {
// si muove
// se è in fondo attende che la gomma sia prelevata
officina.gommaFineNastro(n);
}
La verifica è disponibile qui.
Soluzione commentata del monitor Officina
public class Officina {
/* Il numero di gomme da montare per ogni gruppo di macchine. Corrisponde al numero
* dei gommisti. */
int nGomme;
/* Vettore usato per tenere traccia se è presente una gomma alla fine di un nastro
* (true) o meno (false). Il vettore è di due elementi: quello di indice 0 si riferisce
* al nastro destro, quello di indice 1 al sinistro. */
boolean[] fineNastro;
/* Vettore usato per tenere traccia se un gommista ha montato la ruota (true) o meno (false). */
boolean[] gommaMontata;
/* Usata per modellare il fatto che le auto siano arrivate e in attesa di farsi montare le
* ruote (true) oppure no (false). */
boolean macchineArrivate;
Officina(int nGomme) {
this.nGomme = nGomme;
inizializza();
}
void inizializza() {
/* Dal momento che Java inizializza a false le variabili booleane, è sufficiente creare
* i due vettori. */
fineNastro = new boolean[2];
gommaMontata = new boolean[nGomme];
}
public synchronized void attendiGomma(int id) throws InterruptedException {
/* Attendi se non è presente una gomma al termine del nastro associato al gommista. */
while (!fineNastro[id%2])
wait();
}
public synchronized void prelevataGomma(int id) {
/* Notifica che la gomma è stata raccolta dal gommista. Notare che la gomma può essere
* raccolta solo dal gommista che si trova davanti al nastro, quindi non è necessario
* verificare nuovamente che la posizione sia a true. */
fineNastro[id%2] = false;
notifyAll();
}
public synchronized void gommaFineNastro(int n) throws InterruptedException {
/* Notifica che è presente una ruota al termine del nastro. */
fineNastro[n] = true;
notifyAll();
/* Non riattivare il nastro finché la ruota presente al termine non viene raccolta
* da un gommista. */
while (fineNastro[n])
wait();
}
public synchronized void attendiAuto(int id) throws InterruptedException {
/* Attendi se le macchine non sono ancora arrivate o hai già montato la ruota. */
while (!macchineArrivate || gommaMontata[id])
wait();
}
public synchronized void gommaMontata(int id) {
/* Notifica che il gommista ha montato la ruota che aveva precedentemente raccolto. */
gommaMontata[id] = true;
notifyAll();
}
public synchronized void attendiMontaggioGomme() throws InterruptedException {
/* Notifica ai gommisti l'arrivo delle auto in posizione: ora possono iniziare a
* montare le gomme. */
macchineArrivate = true;
notifyAll();
/* Verifica che tutte le gomme siano state montate. */
for (int i = 0; i < nGomme; i++) {
while (!gommaMontata[i])
wait();
}
/* Riattiva il nastro e segna che tutte le gomme del turno successivo devono ancora
* essere montate. */
macchineArrivate = false;
for (int i = 0; i < nGomme; i++)
gommaMontata[i] = false;
}
}