2012-04-11 18 views
7

Escribí un código simple (adjunto) y no entiendo por qué el bloqueo en algún bloque no está bloqueando el alcance.¿Por qué el bloqueo de este código no funciona?

El código:

object locker = new object(); 
    private void foo(int i) 
    { 
     Console.WriteLine(string.Format("i is {0}", i)); 
     lock(locker) 
     { 
      while(true) 
      { 
       Console.WriteLine(string.Format("i in while loop is {0}", i)) ; 
       foo(++i); 
      } 
     } 
    } 

espero que la llamada para el método foo en el bucle while estará esperando hasta que la taquilla será de liberación (alcance vestuario) - pero todas las llamadas del foo con arg de ++ puedo ingresar al bloque de taquillas.

+0

Creo que es el mismo hilo por lo que no debe bloquearse (tal vez alguien lo sepa con más detalle) – V4Vendetta

+0

Definitivamente aprendí algo nuevo en este caso, +1 –

+11

Si ya estás en el baño, y la puerta está ya bloqueado, y pones un * segundo * en la puerta, * todavía estás en el baño. * –

Respuesta

12

El bloqueo utilizado aquí es reentrante. Se evitará que otro hilo entre en el monitor, pero el hilo que contiene el bloqueo no se bloqueará.

+0

no tenía idea de cómo funcionaba: ¿estás al 100% en este derecho? –

+2

@Gabriel Esto es exactamente correcto; la declaración 'lock' en C# es reentrante. No puedes cerrar "tú mismo". – dlev

+0

eso no es lo que sucede en C/C++, a menos que se grabe mi memoria (y tal vez lo sea) - simplemente sorprendente que nunca me di cuenta de tal diferencia –

7

La palabra clave de bloqueo es solo azúcar sintáctica alrededor de los métodos Monitor.Enter y Monitor.Exit. Como se ve en la documentation para Monitor:

Es legal que el mismo hilo para invocar Introducir más de una vez y sin que el bloqueo;

Calling lock(object) Del mismo hilo más de una vez no tiene otro efecto que aumentar el número de bloqueos.

+0

¿hay otro tipo de bloqueo que se comporte de la manera que el cartel esperaba que se comportara el monitor/bloqueo? –

+1

@Gabriel, podrías usar 'AutoResetEvent' para eso. – svick

+1

@Gabriel 'SpinLock' no es reentrante, IOW,' SpinLonk.Enter' fallará si se solicita el mismo hilo que ya tiene el bloqueo; los dos no son exactamente lo mismo, pero hubieran funcionado como el OP parecía esperar. –

1

Cuando realiza una llamada recursiva aquí en el hilo dice t1, no está girando un hilo separado. La llamada recursiva se realiza en el mismo hilo t1.

Como t1 ya está sosteniendo el candado, no tiene que esperar al candado.

Cuestiones relacionadas