[java] deadlock?

di il
6 risposte

[java] deadlock?

C'è un oggetto ponte che è condiviso tra 10 thread auto. Il ponte è ad una corsia sola ed ha la capacità di 3 auto per volta(per cui e passano una/due/tre auto da una parte,dall'altra non possono passare). Ogni auto per attraversare il ponte impiega 100 ms. La classe ponte ha due metodi portanti : entra() ed esci().
La prima serve a chiedere l'accesso al ponte e ad attraversarlo, la seconda serve per uscire ed avvertire gli altri di essere usciti. L'auto deve avere due direzioni (nord o sud).

Questo è quello che sono riuscito a fare.


MAIN
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package principale;

/**
 *
 * @author fabio
 */
public class Principale {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        
        Ponte ponte = new Ponte();
        Auto []auto = new Auto[10];
        
        for(int i=0;i<auto.length;i++){
            auto[i] = new Auto(ponte);
        }
        
        for(int i=0;i<auto.length;i++){
            auto[i].start();
        }
        
        try{
        for(int i=0;i<auto.length;i++){
            auto[i].join();
        }
        }catch(InterruptedException e){
            System.out.println(e);
        }
        
        
    }
}

OGGETTO CONDIVISO
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package principale;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @author fabio
 */
public class Ponte {
    ReentrantLock lock;
    Semaphore macchine;
    Condition autoNord,autoSud;
    private int nordIn,sudIn;
    private int codaSud,codaNord;
    
    public Ponte(){
        this.lock = new ReentrantLock();
        this.macchine = new Semaphore(3);
        this.autoNord = this.lock.newCondition();
        this.autoSud = this.lock.newCondition();
        this.nordIn = 0;
        this.sudIn = 0;
        this.codaNord = 0;
        this.codaSud = 0;
    }
    
    
    public void Entra(int direzione){
        this.lock.lock();
        try{
            if(direzione == 0)
            {
                while(this.sudIn > 0)
                {
                    this.codaNord++;
                    System.out.println("Auto attende a nord");
                    this.autoNord.await();
                    this.codaNord--;
                }
                this.macchine.acquire();
                System.out.println("Auto entra da nord");
                this.nordIn++;
                
            }
            else 
            {
                while(this.nordIn > 0)
                {
                    this.codaSud++;
                    System.out.println("Auto attende a sud");
                    this.autoSud.await();
                    this.codaSud--;
                }
                this.macchine.acquire();
                System.out.println("Auto entra da sud");
                this.sudIn++;
                
            }
            
        }catch(InterruptedException e){
            System.out.println(e);
        }finally{
            this.lock.unlock();
        }
    }
    
    
    public void Esci(int direzione){
        this.lock.lock();
        try{
            
            if(direzione == 0)
            {
                this.nordIn--; 
                System.out.println("Auto esce da sud");
                this.macchine.release();
                
                if((nordIn == 0) && (codaSud >0))
                {
                    this.autoSud.signalAll();
                }   
                else
                    if(codaNord >0)
                    this.autoNord.signal();
            }
            else
            {
                this.sudIn--;
                System.out.println("Auto esce da nord");
                this.macchine.release();
                
                if((sudIn == 0) && (codaNord >0))
                {
                    this.autoNord.signalAll();
                }
                else
                    if(codaSud >0)
                        this.autoSud.signal();
            }
        }finally{
            this.lock.unlock();
        }
    }
    
}


THREAD
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package principale;

import java.util.Random;

/**
 *
 * @author fabio
 */
public class Auto extends Thread{
    
    private Ponte ponte;
    Random rnd = new Random();
    
    public Auto(Ponte ponte){
        this.ponte = ponte;
    }
    
    @Override
    public void run(){
        
            int x = rnd.nextInt(2);
            this.ponte.Entra(x);
            try{
            sleep(1);
             }catch(InterruptedException e){
            System.out.println(e);
        }
            System.out.println("Provo ad uscire");
            this.ponte.Esci(x);
            
       
    }
}

Il programma gira senza errori. Il problema è che si blocca soltanto nel caso in cui ci sono 3 auto sul ponte che devono uscire, praticamente viene invocato il metodo esci ma il programma si blocca sul lock. Dove sbaglio?

6 Risposte

  • Re: [java] deadlock?

    Intanto: troppi oggetti di sincronizzazzione per un esercizio cosi' semplice.
    Te ne dovrebbe bastare 1 e un contatore:

    -3, -2, -1, 0, 1, 2, 3

    Con tanti oggetti di sinc, il deadlock e' quasi inevitabile. Servono regole cristalline nel loro utilizzo per evitare abbracci mortali
  • Re: [java] deadlock?

    Ho provato a fare come dici ma purtroppo il risultato è sempre lo stesso.
  • Re: [java] deadlock?

    Altre soluzioni??
  • Re: [java] deadlock?

    Crossposting

    http://forum.html.it/forum/showthread.php?threadid=2915140&postid=25248751
  • Re: [java] deadlock?

    minat09 ha scritto:


    Ho provato a fare come dici ma purtroppo il risultato è sempre lo stesso.
    Con un'unico oggetto di sincronizzazione il deadlock e' impossibile!

    Serve un'unico oggetto di sincronizzazione che dice voglio accedere al ponte e un contatore e l'accesso e' consentito solo se e' 0 o un numero < di 3 con il segno che dipende dal lato del ponte.

    Non ci sono altre soluzioni!
    Cioe' le altre sono inutili, magari anche funzionanti, ma inutilmente complicate
  • Re: [java] deadlock?

    migliorabile ha scritto:


    minat09 ha scritto:


    Ho provato a fare come dici ma purtroppo il risultato è sempre lo stesso.
    Con un'unico oggetto di sincronizzazione il deadlock e' impossibile!

    Serve un'unico oggetto di sincronizzazione che dice voglio accedere al ponte e un contatore e l'accesso e' consentito solo se e' 0 o un numero < di 3 con il segno che dipende dal lato del ponte.

    Non ci sono altre soluzioni!
    Cioe' le altre sono inutili, magari anche funzionanti, ma inutilmente complicate
    Certo,credo che il codice sia strutturato proprio in questo modo. Il problema è che si blocca sul lock del metodo Esci() soltanto quando sono dentro 3 auto.
Devi accedere o registrarti per scrivere nel forum
6 risposte