2011-02-03 22 views
37

ho questo codice in Java:nidificati sincronizzato parola chiave

public void doSomeThing() { 
     synchronized (this) { 
      doSomeThingElse(); 
     } 
    } 
    public void doSomeThingElse() { 
     synchronized (this) { 
      // do something else 
     } 
    } 

Può questo blocco di codice? Voglio dire, questo codice può aspettare per sempre?

risposta

47

il blocco del Reentrant java documentation describes per :

un thread può acquisire un blocco che già possiede

Il secondo blocco sincronizzato utilizza lo stesso blocco e quindi sarà sempre utilizzabile poiché la serratura è già stata acquisita nel metodo esterno.

No, non ci sarà un deadlock.

1

Blocco già otturato dal thread che esegue il metodo doSomething, pertanto questo thread può eseguire il metodo doSomethingElse.

Sono necessari due oggetti di blocco per creare una situazione di deadlock. Nel tuo caso, ce n'è solo uno, quindi è impossibile creare un deadlock.

+0

Vuoi dire che il codice [// fa qualcos'altro] può funzionare correttamente? –

+0

Beh, dovrebbe funzionare correttamente .. se non lo è, dovresti pubblicare tutto il codice necessario. –

+0

Significa che il thread ha già il blocco richiesto per il metodo Secound, quindi non si bloccherà. – kasten

3

In un blocco sincronizzato è possibile re-aquire un lucchetto che già possiedi. Il provider di blocco (questo) verrà acquisito dal primo thread per immettere doSomething(). Quindi nel metodo doSomethingElse() lo acquisterà nuovamente.

Il motivo per fare questo? Beh, non c'è niente da dire che non ci sia un'altra discussione che entra in DoSomethingElse da un'altra parte. Ciò impedirà a qualsiasi codice di eseguire il blocco in doSomething() finché il thread in doSomethingElse() non ha rilasciato "this".

Modifica BTW può ovviamente bloccare ... e bloccherà qualsiasi thread che non possiede l'oggetto di sincronizzazione dall'esecuzione. Tuttavia non verrà bloccato (come pubblicato).

0

L'uso sincronizzato in entrambi i casi this quindi se il blocco sincronizzato in doSomeThing è in esecuzione, si dispone già del blocco in modo da poter eseguire il metodo doSomeThingElse.

Se il codice è così semplice, è equivalente a:

public synchronized void doSomeThing() { 
    doSomeThingElse(); 
} 
public synchronized void doSomeThingElse() { 
    // do something else 
} 
0

Hai già preso il blocco del monitor nella prima sincronizzato. Dovresti sempre assicurarti che il design della concorrenza non abbia un impatto enorme sulle prestazioni.

Un modo per garantire questo è sincronizzando solo le istruzioni/codice richiesti.

Diciamo che ora il vostro codice sarà simile a questo.

public void doSomeThing() 
{ 
    synchronized (this) 
    {    
    synchronized (this) 
    {    
     // do something else   
    }   
    }  
} 

considerando che la presente è ciò che è richiesto

public void doSomeThing() 
    { 
     doSomeThingElse();  
    } 
public void doSomeThingElse() 
{ 
synchronized (this) 
     {    
      // do something else   
     } 
} 
7

Se un thread possiede la serratura this, andrà in altri synchronized metodi/blocco come coltello caldo nel burro.

+7

Divide il mio oggetto? Quella metafora ... – Kissaki