2012-06-06 19 views
5

¿Puede alguien explicarme por qué necesitamos el bloqueo anidado?malentendido de bloqueo anidado en C#?

vistazo a este ejemplo:

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

enter image description here

Por favor alguien puede explicar (+ ejemplo será muy apreciada).

+0

¿Quiere decir que el bloqueo se está comprobando en el mismo objeto cada vez, o en diferentes objetos? – Nathan

+0

@Nathan same obj. –

+0

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

Respuesta

13

¿Puede alguien explicarme por qué necesitamos el bloqueo anidado?

Es solo un problema porque es posible que haya anidado (por ejemplo, recursivo recíproco) llamadas a métodos que deben bloquearse. Esos métodos deben permitir que se llame con el recurso ya bloqueado, pero no pueden depender de él. Por lo tanto, el bloqueo anidado es permitido, no necesario.

El código que ha publicado (y el libro al que hace referencia) muestra cómo funciona al reducirlo a un escenario en línea. Ese no es el código "real".

La regla simple es que un hilo que ya posee un bloqueo puede volver a bloquearlo y que el número de salidas debe coincidir con el número de entradas para liberar el bloqueo.

+0

im reading abook about threading. y hay un capítulo especial para él que no entiendo y entonces pregunto. 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 = en & sa = X & ei = qQbPT5zGNorV8gP0q424DA & ved = 0CC0Q6AEwAQ # v = onepage & q =% 22A% 20thread% 20can% 20repeatedly% 20lock% 20the% 20same% 20object% 20in% 20a% 20nested% 20 (reentrant)% 20fashion% 22 & f = falso –

+0

a menos que esté anidando diferentes bloqueos ... pero ese no es el caso en el ejemplo de OP ... –

+3

@RoyiNamir Del libro: "Un hilo * puede * bloquear repetidamente el mismo objeto en un anidado (reentrada) moda ", lo que significa que está permitido, pero no es obligatorio, bloquear un mutex varias veces. – univerio

1

No necesita bloqueo anidado en absoluto como usted menciona.

Pero vale la pena señalar en aras de la claridad que algunos bloqueos pueden anidados. Consulte la clase ReaderWriterLockSlim, donde ingresa como un bloqueo de lectura y luego dentro de ese alcance, puede actualizarlo a un bloqueo de escritura.

EDIT: Como Royi Namir señala, llamando a funciones anidadas cada uno de los cuales tiene su propio candado, será conceptualmente producir el escenario antes mencionado, pero la forma en que se planteó la pregunta, parece que 3 cerraduras están llevando a cabo en el mismo alcance, uno después del otro, lo que tiene menos sentido.

+0

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 = en & sa = X & ei = qQbPT5zGNorV8gP0q424DA & ved = 0CC0Q6AEwAQ # v = onepage & q =% 22A% 20thread% 20can% 20repeatedly% 20lock% 20the% 20same% 20object% 20in% 20a% 20nested% 20 (reentrant)% 20fashion % 22 & f = falso –

5

Existen situaciones en las que la capacidad de anidar bloqueos en el mismo hilo es muy práctica.

Supongamos que tiene una clase con varios métodos. Supongamos que usted quiere tener un esquema de bloqueo muy simple como esto:

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

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

Ahora, si MethodOne llamadas MethodTwo, que tendrían un callejón sin salida en el comienzo de MethodTwo, si no había una capacidad de bloqueo de reentrada en el monitor . El hilo simplemente se habría bloqueado a través del locker.

Afortunadamente, este ejemplo solo funciona en .NET. El casillero "sabe" qué hilo lo ha bloqueado y cuántas veces y dejará pasar (solo) el hilo propietario. El recuento se utiliza para asegurarse de que el desbloqueo desde la perspectiva de otros subprocesos en espera solo se produzca al salir de MethodOne en lugar de al salir de MethodTwo. Este es un ejemplo de bloqueo anidado útil.

Por otro lado, el ejemplo mencionado en la pregunta parece provenir de this book. Los autores querían dejar en claro que el bloqueo anidado es posible en.NET, de forma automática; pero su código de ejemplo está ideado y no pretende aparecer en el código de nadie, excepto cuando se intenta aprender cómo funciona el bloqueo bajo el capó.

+0

¿por qué punto muerto? –

+1

en el caso mencionado, el método dos esperaría que el método uno libere su bloqueo, pero el método uno no soltará el bloqueo hasta que el método dos complete => punto muerto – Nathan

+1

Excelente ejemplo por cierto - +1 – Nathan

2

La respuesta directa a su pregunta es: usted no necesita bloqueo anidado. Sin embargo, el compilador lo permite para hacer que ciertos escenarios sean más fáciles de codificar.

En el código de ejemplo de la pregunta, las cerraduras internas serán siempre exitosas - porque para llegar al bloqueo interno, ya debe haber logrado obtener la cerradura exterior. Su hilo ya tiene un candado en locker y por lo tanto el candado interno "automáticamente" tiene éxito.

Esto nunca es necesario y no proporciona seguridad adicional hilo.

Sin embargo, en situaciones como las publicadas en la respuesta de Jirka Hanika, este comportamiento significa que un miembro seguro para subprocesos puede ser llamado por otro miembro seguro para subprocesos sin tener que preocuparse por interbloqueos.