Si deve gestire la sincronizzazione di N_AUTO che attraversano un incrocio regolato da un semaforo. Il semaforo ha 4 stati: rosso da entrambi i lati, verde in “verticale”, rosso da entrambi i lati, verde in “orizzontale”. Le auto non devono passare con il rosso e scontrarsi. Si comportano secondo il seguente schema:
finché sulla strada:
Se al semaforo:
incrocio.semaforo(direzione); // direzione=true o false a seconda se orizzontale o verticale
// muove la macchina c da (x,y) a (x+dx,y+dy)
// la macchina si muove solo se la strada e' libera
incrocio.muovi(c,x,y,dx,dy);
x+=dx; y+=dy;
incrocio.libera(x,y); // esce e libera (x,y)
Ecco un esempio di situazione con semaforo verde in verticale e rosso in orizzontale:
| V |
| |
| |
| |
| |
| |
| V |
| |
--------------------- o V o ---------------------
V < < < <
> > > > V ^
--------------------- o ^ o ---------------------
| |
| V |
| |
| |
| |
| |
| |
| |
Progettare un monitor Incrocio che implementi i seguenti metodi:
void muovi(char c, int x, int y, int dx, int dy)
se la posizionex+dx,y+dy
è occupata attende. Altrimenti scrivec
in tale posizione e libera
la posizione attualex,y
invocandolibera(x,y)
void libera(int x, int y)
libera la posizionex,y
scrivendo uno spazio (viene invocata quando le auto escono dall’incrocio)void semaforo(Boolean d)
è il semaforo nell’incrocio. viene invocato con un booleano che indica la direzione
(orizzontale o verticale). Il semaforo può essere verde in una direzione o rosso per entrambe
se il semaforo e’ rosso per la direzioned
la macchina attendevoid cambiaSemaforo()
viene invocata periodicamente e cambia lo stato del semaforo. Il semaforo deve ‘ciclare’ tra
quattro stati: rosso per tutti, verde in una direzione, rosso per tutti, verde nell’altra direzione
Scaricare il file zip, modificare Incrocio.java e compilare e eseguire Automobile.java.
Visualizza la soluzione
/* * La verifica consiste nell'implementazione di un monitor per regolare il * movimento delle macchine nei pressi di un incrocio. In particolare, si deve: * - sincronizzare il movimento delle macchine in modo da evitare il * verificarsi di tamponamenti; * - impedire l'attraversamento dell'incrocio se il semaforo è rosso. * Per implementare le operazioni richieste, il monitor usa le seguenti * variabili: * - una matrice di caratteri di dimensione pari all'incrocio, dove ogni cella * contiene uno spazio se la corrispondente posizione è libera, altrimenti * contiene un simbolo che rappresenta la macchina che sta occupando la * corrispondente posizione dell'incrocio; * - un intero che codifica lo stato del semaforo: i valori 0 e 2 codificano il * semaforo rosso in entrambe le direzioni, il valore 1 codifica il verde per * le macchine che si muovono in verticale, il valore 3 codifica il verde per * le macchine che si muovono in orizzonatale; questa scelta dei valori * permette di implementare l'operazione di cambio di stato del semaforo con * un semplice incremento modulo 4. */ public class Incrocio { private char[][] strada; private int semaforo; public Incrocio(int DIM) { /* Alloca una matrice di caratteri per rappresentare lo stato * dell'incrocio e inizializzala con tutte le posizioni libere. */ this.strada = new char[DIM][DIM]; for (int i=0; i<DIM; i++) { for (int j=0; j<DIM; j++) { strada[i][j] = ' '; } } /* Inizialmente il semaforo è rosso in tutte le direzioni * (successivamente diventa verde quello in direzione verticale, * quindi usiamo il valore 0 e non il 2). */ this.semaforo = 0; } public synchronized void muovi(char c, int x, int y, int dx, int dy) throws InterruptedException { /* Attendi se la posizione in cui si deve spostare la macchina è * occupata, in modo da evitare tamponamenti. */ while (strada[x+dx][y+dy] != ' ') { wait(); } /* Occupa la posizione e libera quella precedentemente occupata. */ strada[x+dx][y+dy]= c; libera(x,y); } public synchronized void libera(int x, int y) { /* Ora la posizione è libera. */ strada[x][y] = ' '; /* Notifica il cambiamento alle altre macchine: se una di queste stava * attendendo la liberazione della posizione (x, y), ora può riprovare * ad occuparla. */ notifyAll(); } public char strada(int x, int y) { return strada[x][y]; } public synchronized void semaforo(Boolean d) throws InterruptedException { /* Attendi se il semaforo relativo alla mia direzione di marcia è rosso. * La variabile 'd' è 'true' se la direzione di spostamento è verticale, * 'false' se orizzontale. */ while ((d && semaforo != 1) || (!d && semaforo !=3)) { wait(); } } public synchronized void cambiaSemaforo() { /* Cambia lo stato del semaforo, come descritto sopra. */ semaforo = (semaforo + 1) % 4; /* Notifica il cambiamento alle altre macchine: se una macchina era * in attesa del verde, ora può avere la possibilità di muoversi. * Come piccola ottimizzazione, evitiamo la notifica nel caso il * semaforo diventi rosso in tutte le direzioni, in quanto nessuna * macchina ferma al semaforo potrà muoversi. */ if (semaforo % 2 != 0) { notifyAll(); } } }