2013-03-04 15 views
5

Perché il codice sottostante non causa un deadlock? Voglio dire, dopo chiamo getNumber (.) L'oggetto della classe Test deve essere bloccato, quindi non dovrei essere in grado di accedere a getNumber2 (.).Chiamare un metodo sincronizzato da un metodo sincronizzato, entrambi dello stesso oggetto

class Test() { 
    synchronized int getNumber(int i){ 
     return getNumber2(i); 
    } 

    synchronized int getNumber2(int i) { 
     return i; 
    } 

    public static void main(String[] args) { 
     System.out.println((new Test()).getNumber(100)); 
    } 
} 

uscita:

100 
+0

Post simile a questo: http://stackoverflow.com/questions/5798637/is-it-safe-to-call-a-synchronized-method-from-another-synchronized-method – Walls

+0

Sì, la domanda è la stessa , ma il contesto è piuttosto diverso. Su questa domanda è stato chiesto di blocco morto, l'altro si tratta di thread sicuro. – Lovera

risposta

19

Questo perché la serratura è rientrante, che significa che può essere acquisita più volte dallo stesso filo.

Dal Java tutorial:

Reentrant sincronizzazione

Ricordiamo che il filo non può acquisire un blocco di proprietà di un altro filo. Ma una discussione può acquisire un blocco che già possiede. Consentire a una discussione di acquisire lo stesso blocco più di una volta abilita la sincronizzazione rientrante. Descrive una situazione in cui il codice sincronizzato, direttamente o indirettamente, richiama un metodo che contiene anche codice sincronizzato e entrambi i set di codici utilizzano lo stesso blocco. Senza la sincronizzazione rientranti, il codice sincronizzato dovrebbe prendere molte precauzioni aggiuntive per evitare che un thread si blocchi da solo.

La parte rilevante della JLS è §17.1. Synchronization:

Il linguaggio Java prevede diversi meccanismi per la comunicazione tra i thread. Il più fondamentale di questi metodi è la sincronizzazione, che viene implementata utilizzando i monitor. Ogni oggetto in Java è associato a un monitor, che un thread può bloccare o sbloccare. Solo un thread alla volta può contenere un blocco su un monitor. Qualsiasi altro thread che tenti di bloccare quel monitor viene bloccato fino a quando non è possibile ottenere un blocco su quel monitor. Un thread t può bloccare più volte un determinato monitor; ogni sblocco inverte l'effetto di un'operazione di blocco.

4

Non porta ad un punto morto perché quando un filo immettere un metodo sincronizzato, ciò che fa sta controllando che ha un blocco su this, allora se non lo fa, si attende che può avere il lucchetto e prendilo.

Quando il thread inserisce il secondo metodo sincronizzato nel tuo caso, ha già il blocco sull'oggetto this, in modo che possa immettere il metodo senza bloccare.