2012-06-07 9 views
5

De acuerdo con la especificación del lenguaje lock(obj) statement; se compilará como:¿Cuál es la ventaja de Monitor.Enter (objeto, ref bool) sobre Monitor.Enter (objeto)?

object lockObj = obj; // (the langspec doesn't mention this var, but it wouldn't be safe without it) 
Monitor.Enter(lockObj); 
try 
{ 
    statement; 
} 
finally 
{ 
    Monitor.Exit(lockObj); 
} 

Sin embargo, se compila como:

try 
{ 
    object lockObj = obj; 
    bool lockTaken = false; 
    Monitor.Enter(lockObj, ref lockTaken); 
    statement; 
} 
finally 
{ 
    if (lockTaken) Monitor.Exit(lockObj); 
} 

Eso parece ser mucho más complicado de lo necesario. Entonces, la pregunta es, ¿cuál es la ventaja de esa implementación?

Respuesta

5

Como siempre, Eric Lippert ya ha respondido a esta:

Fabulous Adventures In Coding: Locks and exceptions do not mix

+0

Estaba a punto de responderme después de haber pensado en otra respuesta que lamentablemente se eliminó antes de que pudiera comentar sobre ella. Me hizo pensar más sobre cuándo se podrían lanzar excepciones, si se pueden interrumpir los hilos posiblemente en cualquier lugar, etc. Era bastante obvio que 'Monitor.Enter' podría regresar con éxito, pero antes de que el hilo ingrese al bloque' try' podría interrumpirse. A veces, este sitio es demasiado rápido para honrar a todas las personas que ayudaron a encontrar la respuesta. – Wormbo

2

Hace poco leí en "CLR a través de C#" que podría no ser una ventaja. El razonamiento es que el bloque finally siempre libera el recurso bloqueado, incluso si el bloque try salió como resultado de un error inesperado. Eso podría dejar el recurso en un estado indefinido y accesible. El programa no se estancará, pero el error puede ser mucho más sutil y, por lo tanto, más difícil de encontrar.

Sin duda depende de la situación, pero supongo que la implementación actual de lock tiene más sentido si su prioridad es evitar interbloqueos debido a la interrupción inesperada de los hilos en el peor punto posible.

Cuestiones relacionadas