2010-06-08 11 views
11

Tal vez la pregunta suena tonto, pero no entiendo 'algo acerca de las discusiones y de bloqueo y me gustaría obtener una confirmación (here's why I ask).¿La instrucción lock() bloqueará todos los hilos en el proceso/appdomain?

lo tanto, si tengo 10 servidores y 10 petición en el mismo tiempo llegar a cada servidor, que es 100 petición a través de la granja. Sin bloqueo, eso es 100 solicitudes a la base de datos.

Si hago algo como esto:

private static readonly object myLockHolder = new object(); 
if (Cache[key] == null) 
{ 
    lock(myLockHolder) 
    { 
     if (Cache[key] == null) 
     { 
     Cache[key] = LengthyDatabaseCall(); 
     } 
    } 
} 

¿Cuántas solicitudes de base de datos voy a hacer? 10? 100? ¿O tanto como tengo hilos?

+0

Gracias a todos por las excelentes explicaciones, lo probé y funciona como todos sugirieron - 10 solicitudes de db. – MikeJ

Respuesta

10

Usted tiene una jerarquía de objetos:

  • tiene servidores (10)
  • En cada servidor que tiene procesos (probablemente sólo 1 - su servicio/grupo de aplicación)
  • en cada proceso se han roscas (probablemente muchos)

Su código única prohibir las discusiones dentro del mismo proceso en el mismo servidor de acceso para modificar el Cache objeto simultáneamente. Puede crear bloqueos entre procesos e incluso entre servidores, pero el costo aumenta mucho a medida que asciende en la jerarquía.

El uso de la instrucción lock en realidad no bloquea ningún subproceso. Sin embargo, si un hilo está ejecutando código dentro del bloqueo (que está en el bloque de código que sigue a la declaración lock), cualquier otro hilo que quiera tomar el bloqueo y ejecutar el mismo código debe esperar hasta que el primer hilo que contiene el bloqueo abandone el bloque de código y libera el bloqueo.

La declaración C# lock usa un Windows critical section que es un mecanismo de bloqueo liviano. Si desea bloquear procesos, puede usar un mutex en su lugar. Para bloquear los servidores, puede usar una base de datos o un archivo compartido.

Como dkackman ha señalado, .NET tiene el concepto de un AppDomain que es un tipo de proceso liviano. Puede tener múltiples AppDomains por proceso. La sentencia C# lock solo bloquea un recurso dentro de un único dominio de aplicación, y una descripción adecuada de la jerarquía incluiría el dominio de la aplicación debajo del proceso y encima de los hilos. Sin embargo, con frecuencia solo tienes un dominio de aplicación único en un proceso que hace la distinción algo irrelevante.

+2

Corrección leve "Su código solo prohibirá los subprocesos dentro del mismo dominio de aplicación". La estática de C# está ligada a un Dominio de aplicación, no a un proceso. – dkackman

1

lock bloqueará todos los hilos en que la aplicación de acceso al objeto myLockHolder.

Así que si usted tiene 10 instancias de la aplicación en ejecución que obtendrá 10 peticiones al servidor mientras el objeto está bloqueado en cada uno. En el momento en que salga de la declaración de bloqueo, la siguiente petición procesará en esa aplicación, pero siempre y cuando no es Cache[key]null, no va a tener acceso a la base de datos ..

El número de peticiones reales que se obtiene depende de lo que suceda aquí:

if (Cache[key] == null) 
    { 
    Cache[key] = LengthyDatabaseCall(); 
    } 

Si LengthyDatabaseCall(); falla, la siguiente petición será tratar de acceder al servidor de base de datos y recuperar la información, así que realmente su mejor de los casos es que sólo habrá 10 peticiones al servidor.

0

Sólo los hilos que necesitan acceso a la variable compartida por el momento otro hilo está utilizando voy a entrar en un estado de espera.

cuántos que es en cualquier dará tiempo es difícil de determinar.

2

La sentencia C# lock se bloquea en una instancia particular de un objeto (el objeto que ha creado con new object()). Los objetos (en la mayoría de los casos) no se comparten en AppDomains, por lo tanto, si tiene 10 servidores, se pueden ejecutar 10 subprocesos para acceder simultáneamente a su base de datos con ese fragmento de código.

0

Su DB obtendrá 10 solicitudes, con probabilidades de ser bueno que solicita 2-10 de ejecución mucho más rápida que la solicitud 1.

2

bloqueo no está bloqueando las discusiones. Está bloqueando alguna instancia de un objeto. Y cada hilo que intenta acceder está bloqueado. Por lo tanto, en su caso, cada hilo que intente acceder a myLockHolder se bloqueará y no todos los hilos. En otras palabras, podemos decir que Lock statement es azúcar sintáctico para usar Critical Section.

Como se puede ver en MSDN:

bloqueo bloque (expresión) sentencia

donde:

expresión Especifica el objeto que desea bloquear sucesivamente. expresión debe ser un tipo de referencia. Por lo general, expresión o será esto, si desea proteger una variable de instancia, o typeof (clase), si quieres proteger una variable estática (o si la sección crítica se produce en un método estático en el clase dada).

bloque de instrucción Las declaraciones de la sección crítica.

Cuestiones relacionadas