2012-06-06 17 views
5

Qualcuno può spiegarmi perché abbiamo bisogno di un blocco annidato?Errore di chiusura nidificato in C#?

un'occhiata a questo esempio:

lock (locker) 
    lock (locker) 
    lock (locker) 
     { 
     ... 
     } 

enter image description here

qualcuno può spiegare (+ esempio sarà molto apprezzato).

+0

vuoi dire che il blocco viene controllato sullo stesso oggetto ogni volta o su oggetti diversi? – Nathan

+0

@Nathan stesso oggetto. –

+0

Correlati: http://stackoverflow.com/questions/12013089/when-would-you-ever-use-nested-locking –

risposta

13

Qualcuno può spiegarmi perché abbiamo bisogno di un blocco annidato?

È solo un problema perché è possibile che si abbiano chiamate nidificate (ad esempio reciprocamente ricorsive) a metodi che devono essere bloccati. Questi metodi devono consentire di essere richiamati con la risorsa già bloccata ma non possono dipendere da essa. Il blocco annidato è consentito, non necessario.

Il codice che hai pubblicato (e il libro a cui fai riferimento) mostra come funziona riducendolo a uno scenario in linea. Questo non è un codice "reale".

La regola semplice è che un thread che già possiede un blocco può bloccarlo di nuovo e che il numero di Exits deve corrispondere al numero di Enters per rilasciare il blocco.

+0

sto leggendo un libro sulla filettatura. e c'è un capitolo speciale per questo che non capisco e così chiedo. http://books.google.co.il/books?id=VENrFSQFco8C&pg=PA813&lpg=PA813&dq=%22A+thread+can+repeatedly+lock+the+same+object+in+a+nested+(reentrant)+fashion% 22 & source = bl & OTS = 3uU4rnd_9P & sig = 5NNh4Jbi7pVEZrLydrrs_bOhsBc & hl = it & sa = X & ei = qQbPT5zGNorV8gP0q424DA & ved = 0CC0Q6AEwAQ # v = onepage & q =% 22A% 20thread% 20can% 20repeatedly% 20lock% 20the% 20same% 20object% 20in% 20a% 20nested% 20 (rientrante)% 20fashion% 22 & f = false –

+0

a meno che non si annidino blocchi diversi ... ma questo non è il caso nell'esempio OP ... –

+3

@RoyiNamir Dal libro: "Un thread * può * bloccare ripetutamente lo stesso oggetto in un nidificato (rientrante) moda ", il che significa che è permesso, ma non richiesto, di bloccare un mutex più volte. – univerio

1

Non hai bisogno di un blocco annidato, come dici tu.

Tuttavia, per motivi di chiarezza, è importante sottolineare che alcune serrature possono essere nidificate. Scopri la classe ReaderWriterLockSlim, in cui inserisci come blocco di lettura e quindi all'interno di tale ambito, puoi aggiornarlo a un blocco di scrittura.

EDIT: Come Royi Namir sottolinea, chiamando funzioni annidate ognuno dei quali ha il proprio lucchetto, sarà concettualmente produrrà lo scenario di cui sopra, ma il modo in cui si pone la questione, sembra che 3 serrature sono stato fatto nel stesso ambito, uno dopo l'altro, che ha meno senso.

+0

http://books.google.co.il/books?id=VENrFSQFco8C&pg=PA813&lpg=PA813&dq=%22A+team+può+prevedibilmente+cancellare+l'oggetto+soggetto+in+un+++++per+naturalizzato % 22 & source = bl & OTS = 3uU4rnd_9P & sig = 5NNh4Jbi7pVEZrLydrrs_bOhsBc & hl = it & sa = X & ei = qQbPT5zGNorV8gP0q424DA & ved = 0CC0Q6AEwAQ # v = onepage & q =% 22A% 20thread% 20can% 20repeatedly% 20lock% 20the% 20same% 20object% 20in% 20a% 20nested% 20 (rientrante)% 20fashion % 22 & f = false –

5

Ci sono situazioni in cui la possibilità di annidare i blocchi sullo stesso thread è molto pratica.

Supponiamo di avere una classe con più metodi. Supponiamo che si desidera avere una molto semplice schema di blocco in questo modo:

class A 
{ 
    public void MethodOne() 
    { 
     using (locker) 
     { 
      ...body... 
     } 
    } 

    public void MethodTwo() 
    { 
     using (locker) 
     { 
      ...body... 
     } 
    } 
} 

Ora, se MethodOne chiamate MethodTwo, si avrebbe una situazione di stallo a inizio MethodTwo, se non ci fosse una capacità di bloccaggio rientrante nel monitor . Il thread avrebbe semplicemente bloccato se stesso attraverso il locker.

Fortunatamente, questo esempio funziona solo in .NET. L'armadietto "sa" quale thread lo ha bloccato e quante volte lascerà passare (solo) il thread proprietario. Il conteggio viene utilizzato per assicurarsi che lo sblocco dalla prospettiva di altri thread in attesa si verifichi solo quando si esce da MethodOne anziché uscire da MethodTwo. Quindi questo è un esempio di utile blocco annidato.

D'altro canto, l'esempio menzionato nella domanda sembra venire da this book. Gli autori volevano chiarire che il blocco nidificato è possibile inNET, automaticamente; ma il loro codice di esempio è ideato e non è destinato a comparire nel codice di nessuno, tranne quando si cerca di imparare come funziona il blocco sotto il cofano.

+0

why deadlock ?? –

+1

nel caso citato, il metodo due aspetterebbe il metodo uno per rilasciare il suo blocco, ma il metodo uno non rilascerebbe il blocco finché il metodo due completato => deadlock – Nathan

+1

Esempio eccellente btw - +1 – Nathan

2

La risposta diretta alla tua domanda è: tu non è necessario il blocco nidificato. Tuttavia, il compilatore lo consente per rendere certi codici più facili da codificare.

Nel codice di esempio della domanda, le serrature interne corrisponderanno a sempre - perché per ottenere il blocco interno, è già stato possibile ottenere il blocco esterno. Il thread ha già un blocco su locker e quindi il blocco interno "automaticamente" ha esito positivo.

Questo non è mai necessario e non fornisce ulteriore sicurezza thread.

Tuttavia, in scenari come quelli pubblicati nella risposta di Jirka Hanika, questo comportamento indica che un membro thread-safe può essere chiamato da un altro membro thread-safe senza doversi preoccupare di deadlock.