Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    Dubbio sull'utilizzo dei semafori

    Salve, sto provando a fare esercizi sulla programmazione concorrente in Java ma ho un dubbio sull'utilizzo dei semafori per leggere da una risorsa condivisa.

    La traccia dell'esercizio è questa:

    Delle persone frequentano una piscina per esercitarsi nel nuoto. La piscina è composta da 5 corsie, ciascuna delle quali può essere usata al più da 4 persone contemporaneamente. Ogni persona sceglie la corsia occupata dal mi-nor numero di persone: se la piscina è al completo, sceglie una corsia in maniera casuale e attende in ordine FIFO. Non appena entra in corsia, nuota per un tempo tra 30 e 60 minuti, quindi si fa la doccia (20 minuti), dopodiché va via. La piscina è gestita da un istruttore che deve controllare tutte le attività che si svolgono nelle corsie. L’istruttore ogni giorno gestisce due turni: la mattina tiene aperta la piscina per 4 ore, poi fa una pausa di 1 ora, e riapre la piscina per il turno pomeridiano di 5 ore. Nessuna persona può entrare in piscina se non è presente l’istruttore. Alla chiusura della piscina (sia alla pausa sia alla chiusura finale), se sono presenti delle persone nelle corsie, l’istruttore forza le persone ad uscire dalla piscina. Le persone devono immediatamente liberare la piscina, terminando in anticipo l’attività in acqua e andando subito a fare la doccia.

    Per implementare le corsie uso i due seguenti array:
    codice:
    int[] corsie=new int[5];
    Semaphore[] corsieSem=new Semaphore[5];
    ed inizializzo ogni semaforo a 4.

    Il mio dubbio è il seguente: nel metodo che si occupa di scegliere la corsia meno affollata, quindi che cerca l'indice del minimo nell'array di interi, devo utilizzare un semaforo di mutua esclusione? Io credo di si, ed ho trovato queste soluzione, ma non ne sono sicuro:
    codice:
    private Semaphore mutexCorsie=new Semaphore(1);
    
    int corsiaMenoOccupata() throws InterruptedException {        
            mutexCorsie.acquire();
            int indiceMin=indiceMin(corsie);
            if(corsie[indiceMin]==4){
                mutexCorsie.release();
                return random.nextInt(5);
            }
            mutexCorsie.release();
            return indiceMin;
    }
    Grazie per l'eventuale risposta.
    Ultima modifica di SimoneTR3; 09-06-2017 a 12:11

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Innanzitutto, premessa: non è sempre facile (te lo posso garantire!) rappresentare in classi/oggetti delle logiche e dei comportamenti di persone che usano cose e tempistiche come quanto indicato nella traccia. Insomma, non è facile rappresentare scenari reali di vita.

    In questi casi bisogna analizzare bene le entità in gioco, valutare come rappresentarle e come metterle in relazione. Hai fatto questo? Tutto questo infatti viene PRIMA di qualunque questione o dubbio sui semafori!

    Le persone e l'istruttore potrebbero essere dei "thread". Io farei sicuramente anche una classe Corsia (che contiene il Semaphore, che può anche essere tenuto nascosto) e altrettanto sicuramente farei anche una classe Piscina (che contiene le N corsie).

    Siccome l'istruttore ha di certo un maggiore controllo sulla piscina rispetto alle persone-utenti, se proprio si volesse (scenario limite, da pignoli) si potrebbe astrarre la cosa in due interfacce distinte, implementate entrambe da Piscina. In modo che gli utenti non possano fare operazioni che invece l'istruttore può fare.

    Ti ritrovi con quanto detto? O no?
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Innanzitutto, premessa: non è sempre facile (te lo posso garantire!) rappresentare in classi/oggetti delle logiche e dei comportamenti di persone che usano cose e tempistiche come quanto indicato nella traccia. Insomma, non è facile rappresentare scenari reali di vita.

    In questi casi bisogna analizzare bene le entità in gioco, valutare come rappresentarle e come metterle in relazione. Hai fatto questo? Tutto questo infatti viene PRIMA di qualunque questione o dubbio sui semafori!

    Le persone e l'istruttore potrebbero essere dei "thread". Io farei sicuramente anche una classe Corsia (che contiene il Semaphore, che può anche essere tenuto nascosto) e altrettanto sicuramente farei anche una classe Piscina (che contiene le N corsie).

    Siccome l'istruttore ha di certo un maggiore controllo sulla piscina rispetto alle persone-utenti, se proprio si volesse (scenario limite, da pignoli) si potrebbe astrarre la cosa in due interfacce distinte, implementate entrambe da Piscina. In modo che gli utenti non possano fare operazioni che invece l'istruttore può fare.

    Ti ritrovi con quanto detto? O no?
    Mi trovo assolutamente con la tua soluzione, ed infatti il metodo che ho riportato sopra appartiene ad una classe PiscinaSem. Siccome effettivamente è molto fuori contesto, inserisco tutta l'implementazione che ho detto della classe Piscina, escludendo i metodi da esporre all'istruttore. La traccia richiede sia una implementazione coi semafori che una con lock e condition, PiscinaSem estende Piscina che è una classe astratta che definisce i metodi principali da esportare ai threads.

    codice:
    public class PiscinaSem extends Piscina{	private Random r=new Random();
    	private int[] corsie;
    	private boolean eAperta;
    	private Semaphore mutexCorsie;
    	private Semaphore[] corsieSem;
    	private Semaphore mutexBool;
    	
    	public PiscinaSem(){
    		corsie=new int[4];
    		eAperta=false;
    		mutexCorsie=new Semaphore(1);
    		mutexBool=new Semaphore(1);
    		corsieSem=new Semaphore[5];
    		for(int i=0;i<5;i++){
    			corsieSem[i]=new Semaphore(4,true);
    		}
    	}
    	@Override
    	int corsiaMenoOccupata() throws InterruptedException {
    		mutexCorsie.acquire();
    		int indiceMin=indiceMin(corsie);
    		if(corsie[indiceMin]==4){
    			mutexCorsie.release();
    			return r.nextInt(5);
    		}
    		mutexCorsie.release();
    		return indiceMin;
    	}
    
    
    	private int indiceMin(int[] corsie2) {
    		int indice=0,min =corsie[0];
    		for(int i=0;i<corsie.length;i++){
    			if(corsie[i]<min){
    				indice=i;
    				min=corsie[i];
    			}
    		}
    		return indice;
    	}
    	@Override
    	void entraENuota(int numeroCorsia) throws InterruptedException {
    		corsieSem[numeroCorsia].acquire();
    		mutexCorsie.acquire();
    		corsie[numeroCorsia]++;
    		System.out.println(super.toString());
    
    
    		mutexCorsie.release();
    	}
    
    
    	@Override
    	void docciaEdEsci(int numeroCorsia) throws InterruptedException {
    		mutexCorsie.acquire();
    		corsie[numeroCorsia]--;
    		mutexCorsie.release();
    		corsieSem[numeroCorsia].release();
    	}
    }
    I thread, molto semplicemente, vengono costruiti con un'istanza di Piscina e vi accedono utilizzando i metodi implementati.

    Ho fatto qualche test e sembra funzionare, l'unico vero dubbio è sulla scelta del semaforo di mutua esclusione per leggere il minimo. Anche se non effettuo modifiche, uso la mutua esclusione perchè potrebbe essere modificato il valore di uno dei componenti dell'array dagli altri metodi, e potrei quindi avere una lettura sbagliata del minimo.

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.