Pregunta

Entiendo la función principal de la palabra clave de bloqueo de MSDN

Declaración de bloqueo (referencia de C#)

El bloqueo de la palabra clave marca un bloque de instrucción como una sección crítica al obtener el bloqueo de exclusión mutua para un objeto dado, ejecutar una declaración y luego liberar el bloqueo.

¿Cuándo se debe utilizar la cerradura?

Por ejemplo, tiene sentido con aplicaciones multiproceso porque protege los datos.¿Pero es necesario cuando la aplicación no genera otros hilos?

¿Hay problemas de rendimiento con el uso del bloqueo?

Acabo de heredar una aplicación que usa bloqueo en todas partes, es de un solo subproceso y quiero saber si debo dejarlos ahí, ¿son necesarios?

Tenga en cuenta que esto es más una pregunta de conocimiento general, la velocidad de la aplicación está bien, quiero saber si ese es un buen patrón de diseño a seguir en el futuro o debería evitarse a menos que sea absolutamente necesario.

¿Fue útil?

Solución

¿Cuándo se debe utilizar la cerradura?

Se debe utilizar un candado para proteger los recursos compartidos en código multiproceso.No por nada más.

¿Pero es necesario cuando la aplicación no genera otros hilos?

Absolutamente no.Es sólo una pérdida de tiempo.Sin embargo, asegúrese de no utilizar implícitamente subprocesos del sistema.Por ejemplo, si utiliza E/S asincrónicas, puede recibir devoluciones de llamada de un hilo aleatorio, no del hilo original.

¿Hay problemas de rendimiento con el uso del bloqueo?

Sí.No son muy grandes en una aplicación de un solo subproceso, pero ¿por qué hacer llamadas que no necesitas?

...si ese es un buen patrón de diseño a seguir en el futuro[?]

Bloquear todo, quiera o no, es un patrón de diseño terrible.Si su código está lleno de bloqueos aleatorios y luego decide usar un hilo en segundo plano para algún trabajo, es probable que se encuentre con puntos muertos.Compartir un recurso entre varios subprocesos requiere un diseño cuidadoso y cuanto más pueda aislar la parte complicada, mejor.

Otros consejos

Todas las respuestas aquí parecen correctas:La utilidad de los bloqueos es impedir que los subprocesos accedan al código bloqueado al mismo tiempo.Sin embargo, hay muchas sutilezas en este campo, una de las cuales es que los bloques de código bloqueados se marcan automáticamente como regiones críticas por Common Language Runtime.

El efecto de que el código se marque como crítico es que, si no se puede ejecutar toda la región, el tiempo de ejecución puede considerar que todo su dominio de aplicación está potencialmente en peligro y, por lo tanto, descargarlo de la memoria.Citar MSDN:

Por ejemplo, considere una tarea que intenta asignar memoria mientras se mantiene un bloqueo.Si falla la asignación de memoria, cancelar la tarea actual no es suficiente para garantizar la estabilidad del AppDomain, porque puede haber otras tareas en el dominio esperando el mismo bloqueo.Si se finaliza la tarea actual, otras tareas podrían quedar estancadas.

Por lo tanto, aunque su aplicación sea de un solo subproceso, esto puede representar un peligro para usted.Considere que un método en un bloque bloqueado genera una excepción que eventualmente no se maneja dentro del bloque.Incluso si la excepción se soluciona a medida que surge a través de la pila de llamadas, su región crítica de código no finalizó normalmente.¿Y quién sabe cómo reaccionará el CLR?

Para más información, lea este artículo sobre los peligros de Thread.Abort().

Tenga en cuenta que puede haber razones por las que su aplicación no sea tan monoproceso como cree.La E/S asíncrona en .NET bien puede devolver la llamada a un subproceso de grupo, por ejemplo, al igual que algunas de las distintas clases de temporizador (aunque no el temporizador de Windows Forms).

En términos generales, si su aplicación es de un solo subproceso, no obtendrá mucho uso de la declaración de bloqueo.Al no conocer exactamente su aplicación, no sé si son útiles o no, pero sospecho que no.Además, si su aplicación usa bloqueo en todas partes, no sé si me sentiría tan seguro de que funcione en un entorno de subprocesos múltiples, ¿lo hizo el desarrollador original? de hecho ¿Saben cómo desarrollar código multiproceso, o simplemente agregaron declaraciones de bloqueo en todas partes con la vaga esperanza de que eso funcionara?

El bloqueo debe usarse alrededor del código que modifica el estado compartido, el estado que es modificado por otros subprocesos simultáneamente, y esos otros subprocesos deben tomar el mismo bloqueo.

Un bloqueo es en realidad un serializador de acceso a la memoria, los subprocesos (que toman el bloqueo) esperarán a que el bloqueo entre hasta que el subproceso actual salga del bloqueo, por lo que el acceso a la memoria se serializa.

Para responder a su pregunta, el bloqueo no es necesario en una aplicación de un solo subproceso y tiene efectos secundarios en el rendimiento.porque los bloqueos en C# se basan en objetos de sincronización del kernel y cada bloqueo que realiza crea una transición al modo kernel desde el modo usuario.

Si está interesado en el rendimiento de subprocesos múltiples, un buen lugar para comenzar es Directrices de subprocesamiento de MSDN

poder Tiene problemas de rendimiento con el bloqueo de variables, pero normalmente construiría su código para minimizar el tiempo que se pasa dentro de un bloque de código "bloqueado".

En cuanto a quitar las cerraduras.Dependerá de qué esté haciendo exactamente el código.Aunque es de un solo subproceso, si su objeto se implementa como Singleton, es posible que tenga varios clientes usando una instancia del mismo (en la memoria, en un servidor) al mismo tiempo.

Sí, habrá alguna penalización en el rendimiento al usar el bloqueo, pero generalmente es lo suficientemente insignificante como para no importar.

El uso de bloqueos (o cualquier otra declaración o construcción de exclusión mutua) generalmente solo es necesario en escenarios de subprocesos múltiples donde múltiples subprocesos (ya sea de su propia creación o de la persona que llama) tienen la oportunidad de interactuar con el objeto y cambiar el estado subyacente o datos mantenidos.Por ejemplo, si tiene una colección a la que pueden acceder varios subprocesos, no desea que un subproceso cambie el contenido de esa colección eliminando un elemento mientras otro subproceso intenta leerlo.

Lock(token) solo se usa para marcar uno o más bloques de código que no deben ejecutarse simultáneamente en varios subprocesos.Si su aplicación tiene un solo subproceso, está protegida contra una condición que no puede existir.

Y el bloqueo provoca un impacto en el rendimiento, agregando instrucciones para verificar el acceso simultáneo antes de ejecutar el código.Sólo debe utilizarse cuando sea necesario.

Ver el pregunta sobre 'Mutex' en C#.Y luego mira estos dos preguntas sobre el uso de la declaración 'lock(Object)' específicamente.

No tiene sentido tener bloqueos en la aplicación si solo hay un hilo y sí, es un impacto en el rendimiento, aunque se necesita una buena cantidad de llamadas para que ese impacto se convierta en algo significativo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top