2010-02-16 13 views
6

Di seguito è riportato il codice direttamente dai tutorial Sun che descrive Deadlock. Tuttavia, non capisco come si possa verificare Deadlock in questa situazione considerando entrambi i metodi sincronizzati. In che modo due thread si trovano all'interno degli stessi metodi sincronizzati allo stesso tempo?Una domanda su Deadlock dai tutorial Sun

Deadlock descrive una situazione in cui due o più thread sono bloccati per sempre, in attesa l'uno dell'altro. Ecco un esempio.

Alphonse e Gaston sono amici e grandi credenti in segno di cortesia. Una rigida regola di cortesia è che quando ti inchini ad un amico, devi rimanere inchinato finché il tuo amico non ha la possibilità di restituire l'arco. Sfortunatamente, questa regola non tiene conto della possibilità che due amici si pieghino l'un l'altro allo stesso tempo. Questa applicazione di esempio, Deadlock, modelli questa possibilità:

public class Deadlock { 
    static class Friend { 
     private final String name; 
     public Friend(String name) { 
      this.name = name; 
     } 
     public String getName() { 
      return this.name; 
     } 
     public synchronized void bow(Friend bower) { 
      System.out.format("%s: %s has bowed to me!%n", 
        this.name, bower.getName()); 
      bower.bowBack(this); 
     } 
     public synchronized void bowBack(Friend bower) { 
      System.out.format("%s: %s has bowed back to me!%n", 
        this.name, bower.getName()); 
     } 
    } 

    public static void main(String[] args) { 
     final Friend alphonse = new Friend("Alphonse"); 
     final Friend gaston = new Friend("Gaston"); 
     new Thread(new Runnable() { 
      public void run() { alphonse.bow(gaston); } 
     }).start(); 
     new Thread(new Runnable() { 
      public void run() { gaston.bow(alphonse); } 
     }).start(); 
    } 
} 

Quando Deadlock corre, è estremamente probabile che entrambi i fili bloccheranno quando tentano di richiamare bowBack. Nessun blocco finirà mai, perché ogni thread sta aspettando che l'altro esca dall'arco.

+1

possibile duplicato di [Cercando di avvolgere il mio cervello su come si blocca il thread] (http://stackoverflow.com/questions/749641/trying-to-wrap-my-wee-brain-around-how-threads-deadlock –

risposta

7

I metodi sincronizzati (istanza) bloccano l'oggetto, NON sulla classe.

alphonse.bow afferra la serratura su alphonse e gaston.bow afferra la serratura su gaston. Quando il filo "alphonse" è in prua, cerca di afferrare il blocco "gaston" a bower.bowBack. Allo stesso modo, 'gaston' cerca di aggrapparsi al blocco 'alphonse'.

Edit per chiarezza (spero):

Chiamiamo i due fili Thread1 e Thread2.

Thread1 esegue alphonse.bow (gaston), dove afferra il blocco sull'oggetto alphonse mentre Thread2 esegue gaston.bow (alphonse) e afferra il blocco sull'oggetto gaston.

In Thread1, quando tenta di eseguire bower.bowBack (this), dove bower = gaston, il thread deve prima acquisire il blocco su gaston.

Mentre sta succedendo, Thread2 prova a fare la stessa cosa, con bower = alphonse. Thread1 ha un lock di cui Thread2 ha bisogno e viceversa, motivo per cui si verifica il deadlock.

Per inciso, non sempre si verifica un deadlock. Se Thread1 può iniziare e finire prima che Thread2 abbia la possibilità di farlo (ad es. Se qualcosa blocca il thread principale dopo aver avviato Thread1 ma prima che Thread2 sia stato creato/avviato), non si verificherà alcun deadlock.

+0

come alphonse tenta di ottenere un blocco su gaston. alphonse usa sempre l'istanza alphonse. – jax

+0

Non capisco quanto segue "Quando il thread 'alphonse' è in prua, prova ad agguantare il blocco 'gaston' a bower.bowBack." In che modo "alphonse" sta cercando di ottenere un blocco sull'istanza di gaston. – jax

+0

Il primo thread chiama alphonse.bow (gaston). A questo punto, il thread ha un blocco su alphonse. Una volta che il metodo scende a bower.bowBack, dove bower è gaston, cerca di ottenere il lock su gaston. Per "alphonse" intendevo il thread che eseguiva "alphonse.bow (gaston)"; scusa se non era chiaro. –