Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 23
  1. #1

    [java] gestione politiche priorità in un sistema produttore/consumatore (threads)

    salve a tutti, vorrei una mano per quanto riguarda la programmazione di threads in particolare per la gestione delle politiche di priorità.
    devo sviluppare un sistema produttore/consumatore con n threads produttori e m threads consumatori i quali sono a sua volta suddivisi in consumatori di tipo A e di tipo B

    il problema che mi affligge oramai da 2 settimane e che non ho risolto anche con le infinite ricerche su internet è la gestione della politica della priorità.
    i threads consumatori di tipo B possono prelevare dati dal vettore condiviso (dimensione limitata) solo se non esistono in attesa threads consumatori di tipo A.

    per ora ho sviluppato tutto con l'uso dei semafori come nel sistema prod/cons generale.

    idee:
    1)le classi produttore e consumatoreA sono uguali a quelle usate per il classico produttore/consumatore e la classe consumatoreB che in più controlla se ci sono threads consumatoreA in attesa altrimenti "consuma" dato dal vettore (ma come fare??)
    2)uso di notify, notifyAll... ma non so come usarle bene...

    insomma, non so come comportarmi... se c'è qualcuno che ha anche una piccola idea mi faccia sapere... vi prego!!

    grazie.

  2. #2
    Ma cosi' l'unico modo che i consumatori di tipo B hanno di prelevare i dati e' quando i consumatori di tipo A sono passati allo stato dead!!
    Per fare tale differenza nel prelevare i dati devi impostare una variabile di condizione per la risorsa condivisa, non so se A mangia patate e nel cesto ci sono uova dai l'accesso a B.
    O altrimenti spiega i dati che sono in gioco.
    Un thread che attende un lock su una risorsa condivisa di solito si trova in un ciclo senza fine per tentare il loock sulla risorsa.
    Nulla, ma e' sempre qualcosa.

  3. #3
    l'idea iniziale era fare 6 classi:
    Principale - contiene il main che con 3 cicli for manda in esecuzione i threads produttore, j threads consumatoreA e k threads consumatoreB
    Produttore - ConsumatoreA - ConsumatoreB classi che estendono Thread
    BufferLimitato - implementa un buffer con dimensione limitata a 5 con semafori. il buffer è unico e condiviso con tutti i thread in gioco
    Semaforo - la classe che gestisce una variabile int come un semaforo con metodi P() e V() sincronizzate

    consumatoreA e consumatoreB sono le tipologie dei threads in gioco che prelevano elementi dal vettore di oggetti (Date()) e li stampano a video.

    sia produttore che i due consumatori hanno implementato il metodo run con all'interno un ciclo while(true) [quindi non dovrebbero mai andare in dead?? no??]

    il problema è la questione della politica...
    secondo te non è possibile gestire la politia di priorità semplicemente dando ai threads del tipo B una priorità più bassa rispetto a quella dei threads prod e consA??

    sono agli inizi, se non ti dispiace potresti speigarmi la tua idea in modo dettagliato?? grazie davvero!!!

  4. #4
    No perche' dando una priorita' maggiore non hai la certezza di ottenere i risultati desiderati perche' comunque prima o poi un processore ce l'avranno, puo' succedere che i threads con priorita' piu' bassa abbiano accesso ai dati che non devono essere consumati in un determinato momento, punta a creare una condizione piu' restrittiva migliorando i metodi sincronizzati all'interno della classe che li implementano, non so cerca di qualificare i dati prodotti dal produttore,
    una variabile di condizione sarebbe l'ideale, del tipo
    codice:
       int request = 0;
    
       // produzione dati
    
       if(request ==  0){
          running A
          notifyAll();
        }
        else{
          running B 
          notifyAll();
        }
    Naturalmente questo codice all'interno della classe sincronizzata altrimenti i monitor(notify, wait etc etc)
    non funzionerebbero come si deve.
    Nulla, ma e' sempre qualcosa.

  5. #5
    Folle e' l'uomo che parla alla luna.
    Stolto chi non le presta ascolto.

  6. #6
    codice:
    class BoundedBuffer {
       final Lock lock = new ReentrantLock();
       final Condition notFull  = lock.newCondition(); 
       final Condition notEmpty = lock.newCondition(); 
    
       final Object[] items = new Object[100];
       int putptr, takeptr, count;
    
       public void put(Object x) throws InterruptedException {
         lock.lock();
         try {
           while (count == items.length) 
             notFull.await();
           items[putptr] = x; 
           if (++putptr == items.length) putptr = 0;
           ++count;
           notEmpty.signal();
         } finally {
           lock.unlock();
         }
       }
    
       public Object take() throws InterruptedException {
         lock.lock();
         try {
           while (count == 0) 
             notEmpty.await();
           Object x = items[takeptr]; 
           if (++takeptr == items.length) takeptr = 0;
           --count;
           notFull.signal();
           return x;
         } finally {
           lock.unlock();
         }
       } 
     }
    Nel link da te postato c'e' il seguente esempio, ti va di commentarlo??
    Subito dopo l'intestazione di entrambi i metodi c'e' questa istruzione: lock.lock();
    Tale chiamata conferisce al metodo di essere utilizzato da un solo oggetto quindi viene bloccato e tale blocco viene rilasciato all'esecuzione del'istruzione finally contenente l'istruzione lock.unlock();(rilasci blocco).

    Con la sincronizzazione "classica" i metodi take() e put() sincronizzati, conferiscono all'oggetto che li contiene la sincronizzazione di tutto l'oggetto, questo perche' non ci sono altri metodi non sincronizzati.

    La sincronizzazione nel multithreading porta una certa ineficienza nell'esecuzione di un programma perche' un consumatore puo' trovarsi nella condizione di ottenere un lock piu' volte in maniera consecutiva ma non puo' inserire i dati cancellando quelli precedenti che non sono ancora stati consumati e quindi si ricorre ad un array di oggetti per fare in modo che quando un consumatore o un produttore si trova nella condizione di aver piu' volte consecutivamente un processore possa gestire la plus produzione o la plus consumazione.

    Bhe adesso per proseguire vorrei conferma....
    Nulla, ma e' sempre qualcosa.

  7. #7
    Con la sincronizzazione "classica" i metodi take() e put() sincronizzati, conferiscono all'oggetto che li contiene la sincronizzazione di tutto l'oggetto, questo perche' non ci sono altri metodi non sincronizzati.
    Dal punto di vista del lock, questa classe e' del tutto equivalente alla sincronizzazione classica. Dichiarare un metodo synchronized equivale ad avere un membro lock della classe, una chiamata a lock.lock come prima istruzione del metodo ed una chiamata a lock.unlock come ultima.
    D'altronde a me cosi' li hanno fatti studiare ed implementare in C, al corso di sistemi operativi, coi lock e le condition. E confesso di avere difficolta' ad usare la parola chiave synchronized... Forse perche' non mi ricordo mai come si scrive!

    Quello che cambia qui e' che avendo due code, invece di una, il signal puo' selezionare quali thread svegliare e quali no.

    La sincronizzazione nel multithreading porta una certa ineficienza nell'esecuzione di un programma perche' un consumatore puo' trovarsi nella condizione di ottenere un lock piu' volte in maniera consecutiva ma non puo' inserire i dati cancellando quelli precedenti che non sono ancora stati consumati e quindi si ricorre ad un array di oggetti per fare in modo che quando un consumatore o un produttore si trova nella condizione di aver piu' volte consecutivamente un processore possa gestire la plus produzione o la plus consumazione.
    Beh, piu' che in effecienza, e' il classico "baratto spazio-tempo": spreco un po' di memoria in piu' ma il programma (o quello che e', in generale. Anche nei PC moderni, gran parte dell' aumento di velocita' e' dovuto al fatto che ormai la memoria si butta, e ogni componente possiede notevoli quantita' di buffer) il programma, dicevo, ne guadagna in tempo di risposta.
    Il problema non e' la sincronizzazione in se, ma il fatto che le entita', prese da sole, non sono sincronizzate (d'altronde se gia' lo erano, perche' sincronizzarle?)
    Folle e' l'uomo che parla alla luna.
    Stolto chi non le presta ascolto.

  8. #8
    codice:
    public class BufferLimitato{  
        public static final int SLEEP_TIME = 5;
        private static final int BUFFER_SIZE = 2;
        private Semaforo mutex;
        private Semaforo empty;
        private Semaforo full;
        private int count;
        private int in, out;
        private Object[] buffer;
    	 
        public BufferLimitato(){
        	count=0;
            in=0;
            out=0;
            buffer = new Object[BUFFER_SIZE];
            mutex = new Semaforo(1);
            empty = new Semaforo(BUFFER_SIZE);
            full = new Semaforo(0);
        }
       	
        public BufferLimitato(int size){
        	count=0;
            in=0;
            out=0;
            buffer = new Object[size];    
            mutex = new Semaforo(1);
            empty = new Semaforo(BUFFER_SIZE);
            full = new Semaforo(0);
        }
    
        public static void napping(){
         	int sleepTime=(int)(SLEEP_TIME * Math.random()); 
         	try{ 
         	     Thread.sleep(sleepTime*1000); 
         	}catch(InterruptedException e){ 
         	}
        }
    
        public void inserisce(Object item){
          	empty.P();
          	mutex.P(); 
          	count++;
          	buffer[in]=item;
          	in=(in+1)%BUFFER_SIZE;
          	if(count==BUFFER_SIZE)
                 System.out.println("Produttore ha inserito " + item + " - buffer PIENO");
          	else
                 System.out.println("Produttore ha inserito " + item + " - dimensione buffer = " +  count);
          	mutex.V();
          	full.V();
        }
    
        public Object rimuove(){
          	Object item;  
          	full.P();
          	mutex.P();
          	count--;
          	item=buffer[out];
          	out=(out+1)%BUFFER_SIZE;
          	if(count==0)
                 System.out.println("Consumatore ha consumato " + item + " - Buffer VUOTO");
          	else
                 System.out.println("Consumatore ha consumato " + item + " - dimensione buffer = " + count);
          	mutex.V();
          	empty.V();
          	return item;
        }
    }
    codice:
    public final class Semaforo{
        private int value;
       
        public Semaforo(){
          	value = 0;
        }
       
        public Semaforo(int v){
          	value = v;
        }
       
        public synchronized void P(){
          	while (value<=0){
                 try{
                      wait();
                 }catch (InterruptedException e){ 
                 }
          	}
          	value--;
        }
       
        public synchronized void V(){
          	value++;
          	notify();
        }
    }
    codice:
    public class Produttore extends Thread{
        private BufferLimitato buffer;
    	
        public Produttore (BufferLimitato b){
    	buffer=b;	
        }
    	
        public void run(){
    	Date message;
    	while(true){
    	    BufferLimitato.napping();
    	    message = new Date();
    	    buffer.inserisce(message);
    	}			
        }
    }
    codice:
    public class ConsumatoreA extends Thread{
        private BufferLimitato buffer;
       
        public ConsumatoreA(BufferLimitato b){
             buffer = b;
        }
        
        public void run(){
         	 Date message;
         	 while (true) {
                  BufferLimitato.napping();
                  message = (Date)buffer.rimuove();
                  System.out.println("ConsA: "message);
          	 }
        }
    }
    e consumatoreB è analogo a consumatoreA

    queste sono le classi che ho fatto fino ad ora... penso (in questo momento non sono sicuro di nulla dato che è la prima volte che mi trovo ad affrontare un problema di programmazione sui thread) che dovrò modificare la classe condumatoreB in modo da far gestire la priorità...

    sinceramente non ho capito molto l'ultima parte con il codice... non dovrebbe essere un'implementeazione simile a quella che ho fatto io??

    per quanto riguarda la variabile di controllo...
    il vettore in condivisione è unico e gli oggetti che sono dentro sono tutti uguali... consumatoreA potrà prelevare oggetti dal vettore quando gli pare (naturalmente controllando se c'è o non c'è lock sulla risorsa) e consumatoreB potrà prelevare dati solo se non ci sono thread consumatoreA in stato di attesa...
    cmq i thread consumatoreB dovranno riuscire a prendere il lock sulla risorsa prima o poi...

    qual era la tua idea??

  9. #9
    Ok visto che il codice sopra e' una valida alternativa alla sincronizzazione, volevo aiutare il nostro amico...
    Lui ha due categorie di consumatori e l'unico modo di far differenza nella consumazione dei dati e' qualificando i dati, una partita di tipo A e una partita di tipo B

    il problema che mi affligge oramai da 2 settimane e che non ho risolto anche con le infinite ricerche su internet è la gestione della politica della priorità.
    i threads consumatori di tipo B possono prelevare dati dal vettore condiviso (dimensione limitata) solo se non esistono in attesa threads consumatori di tipo A.
    In pratica i consumatori A saranno sempre alla ricerca di un lock e in questa alternanza lo stato di A sara' sempre o Running o ready(esecuzione, pronto per l'esecuzione) e quindi A sara' sempre in attesa, allora giungo alla conclusione cha debba discriminare i dati, tipo A e tipo B.
    Nulla, ma e' sempre qualcosa.

  10. #10
    Quello che cambia qui e' che avendo due code, invece di una, il signal puo' selezionare quali thread svegliare e quali no.
    nel mio caso la signal sarebbe il mio metodo V?? come fa a selezionare il thread da svegliare??

    sto andando nei pazzi...

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.