2012-11-26 17 views
5

Si consideri il seguente:Processo DeadLock Chi si blocca per primo?

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("\n%S: %S has bowed to me!" , this.name, bower.getName()); 
     bower.bowBack(this); 
    } 
    public synchronized void bowBack(Friend bower) { 
     System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName()); 
    } 


} 

public static void main(String[] args) { 
    final Friend alf = new Friend("Alf"); 
    final Friend arian = new Friend("Arian"); 

    // Thread 1 
      new Thread(new Runnable() { 
     public void run(){ alf.bow(arian);}}).start(); 

    //Thread 2 
    new Thread(new Runnable() { 
     public void run(){ arian.bow(alf);}}).start(); 
} 

}

L'out put è

ALF: ARIAN si è piegato a me! ARIAN: ALF si è inchinato a me!

situazione di blocco .....

quando il filo 1 viene eseguito, si richiede un blocco sul Friend oggetto. Immediatamente dopo tale Thread 2 è necessario bloccare il secondo oggetto. Ora il metodo arco è bloccato dal thread 1 e quindi stampa "ALF: ARIAN mi ha inchinato!". Come entra la Discussione 2 arco e nessuno dei due può immettere * archBack * ??

saluti B.

risposta

5

Tenete a mente che synchronized metodi sempre sincronizzare su this.

Esistono due oggetti e quindi due blocchi. alf.bow() acquisisce alf s lock e arian.bow() acquisisce arian s. Ma poi bowback() prova ad acquisire l'altro, che è quando si verifica il deadlock.

Se si desidera sincronizzare su un oggetto blocco condiviso, si dovrebbe fare qualcosa di simile:

class Friend { 
    private static final Object lock = new Object(); 

    public void bow(...) { 
    synchronized(lock) { 
     ... 
    } 
    } 

    public void bowback(...) { 
    synchronized(lock) { 
     ... 
    } 
    } 

} 

Dal lock si trova in un campo statico, significa tutte le istanze di Friend utilizzano lo stesso oggetto di blocco, quindi, non c'è possibilità di un punto morto.

È anche possibile sincronizzare sull'oggetto classe synchronized(Friend.class) {...}, ma la sincronizzazione su oggetti esterni visibili di solito non è una buona idea in quanto non vi è alcuna garanzia che un'altra parte del codice non rubi il blocco.

+0

Molte molte grazie per i vostri commenti. –

3

La sincronizzazione viene eseguita utilizzando qualsiasi oggetto; i thread possono entrare simultaneamente in blocchi sincronizzati se sono sincronizzati con oggetti diversi.

La parola chiave synchronized in un metodo di istanza indica che il blocco è sincronizzato da tale istanza. Poiché si chiama il metodo bow di due oggetti diversi, non esiste alcun controllo che esegua contemporaneamente tale funzione.

sincronizzare con l'oggetto classe (o utilizzare un oggetto finale statico creato per tale scopo).

1

- Hai usato 2 objects, e sia le discussioni qui stanno utilizzando 2 diversi serrature Monitor.

- Poiché entrambi i fili stanno avendo blocco sul 2 different object, è abbastanza evidente che il bloccaggio del filo 1 sull'oggetto 1 non ha alcun effetto sul filo 2 prendendo la serratura oggetto 2.

- Hai usato synchronized parola chiave che richiedono un blocco oggetto qui, e si sta fornendo sia i fili con le loro serrature proprio oggetto, in modo da infilare 2 inserire l'arco.

1

È necessario bloccare un oggetto comune.

public static void main(String[] args) { 
    final Object lock = new Object(); 
    final Friend alf = new Friend("Alf", lock); 
    final Friend arian = new Friend("Arian", lock); 
    ... 
} 


public void bow(Friend bower){ 
    synchronize(lock){ 
     System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName()); 
     bower.bowBack(this); 
    } 
} 
public void bowBack(Friend bower) { 
    synchronize(lock){ 
     System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName()); 
    } 
} 
Problemi correlati