remarks net example c# .net synchronization locking thread-safety

net - remarks c#



¿Cómo funciona el bloqueo exactamente? (8)

Veo que para usar objetos que no son seguros para hilos, envolvemos el código con un bloqueo como este:

private static readonly Object obj = new Object(); lock (obj) { // thread unsafe code }

Entonces, ¿qué sucede cuando varios subprocesos acceden al mismo código (supongamos que se está ejecutando en una aplicación web ASP.NET)? ¿Están en cola? Si es así, ¿cuánto tiempo van a esperar?

¿Cuál es el impacto en el rendimiento debido al uso de bloqueos?


El impacto en el rendimiento depende de la forma en que se bloquea. Puede encontrar una buena lista de optimizaciones aquí: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Básicamente, debe intentar bloquear lo menos posible, ya que pone el código de espera en suspensión. Si tiene algunos cálculos pesados ​​o un código de larga duración (por ejemplo, carga de archivos) en un bloqueo, se produce una gran pérdida de rendimiento.


Es más sencillo de lo que piensas.

Según Microsoft : la palabra clave de lock garantiza que un subproceso no ingrese a una sección crítica del código mientras que otro subproceso está en la sección crítica. Si otro hilo intenta ingresar un código bloqueado, esperará, bloqueará, hasta que se libere el objeto.

La palabra clave de lock llama Enter al inicio del bloque y Exit al final del bloque. lock palabra clave de lock realmente maneja la clase Monitor en el back-end.

Por ejemplo:

private static readonly Object obj = new Object(); lock (obj) { // critical section }

En el código anterior, el primer subproceso entra en la sección crítica, entonces bloqueará el obj y cuando otro subproceso intente ingresar, también intentará bloquear el obj que ya está bloqueado por el primer subproceso, tendré que esperar que el primer subproceso libere el obj . y cuando saldrá primero, otro hilo bloqueará el objeto y entrará en la sección crítica.


La declaración de lock es traducida por C # 3.0 a lo siguiente:

var temp = obj; Monitor.Enter(temp); try { // body } finally { Monitor.Exit(temp); }

En C # 4.0 esto ha cambiado y ahora se genera de la siguiente manera:

bool lockWasTaken = false; var temp = obj; try { Monitor.Enter(temp, ref lockWasTaken); // body } finally { if (lockWasTaken) { Monitor.Exit(temp); } }

Puede encontrar más información sobre lo que Monitor.Enter hace here . Para citar MSDN:

Utilice Enter para adquirir el Monitor en el objeto pasado como parámetro. Si otro subproceso ha ejecutado un Enter en el objeto pero aún no ha ejecutado la Exit correspondiente, el subproceso actual se bloqueará hasta que el otro subproceso libere el objeto. Es legal que el mismo hilo invoque Enter más de una vez sin que se bloquee; sin embargo, debe invocarse un número igual de llamadas de Exit antes de que se desbloqueen otros subprocesos que esperan en el objeto.

El método Monitor.Enter esperará infinitamente; no va a expirar.


La declaración de lock se traduce en llamadas a los métodos de Enter y Exit del Monitor .

La instrucción de lock esperará indefinidamente a que se libere el objeto de bloqueo.


La parte dentro de la sentencia de bloqueo solo puede ser ejecutada por un subproceso, por lo que todos los otros subprocesos esperarán indefinidamente a que finalice el subproceso que mantiene el bloqueo. Esto puede resultar en un llamado interbloqueo.


Los bloqueos impedirán que otros subprocesos ejecuten el código contenido en el bloque de bloqueo. Los hilos tendrán que esperar hasta que el hilo dentro del bloque de bloqueo se haya completado y el bloqueo se libere. Esto tiene un impacto negativo en el rendimiento en un entorno multiproceso. Si necesita hacer esto, debe asegurarse de que el código dentro del bloqueo de bloqueo pueda procesarse muy rápidamente. Debe intentar evitar actividades costosas como acceder a una base de datos, etc.


No, no están en cola, están durmiendo.

Una declaración de bloqueo de la forma

lock (x) ...

donde x es una expresión de un tipo de referencia, es exactamente equivalente a

var temp = x; System.Threading.Monitor.Enter(temp); try { ... } finally { System.Threading.Monitor.Exit(temp); }

Solo debes saber que están esperando el uno al otro, y solo un hilo ingresará para bloquear el bloqueo, los otros esperarán ...

El monitor está escrito completamente en .net, por lo que es lo suficientemente rápido, también consulte la clase Monitor con reflector para obtener más detalles