thread synlock lock example español async c# multithreading locking

synlock - thread synchronization c#



¿Por qué "lock(typeof(MyType))" es un problema? (6)

Debido a que el resultado de typeof (MyType) (que es un objeto de tipo Type ) es ampliamente accesible y otro subproceso puede bloquearse en el mismo objeto y mantener ese bloqueo indefinidamente. Entonces, la lógica interna de MyType efectivamente ha otorgado un control significativo sobre su lógica de sincronización. Esto podría no ser un problema real si esto es así, pero la codificación defensiva / escéptica debería ser su modus operandi .

MSDN da la siguiente advertencia sobre la palabra clave de bloqueo en C #:

En general, evite bloquear un tipo público o instancias más allá del control de su código. El bloqueo común de construcciones (this), lock (typeof (MyType)) y lock ("myLock") violan esta directriz:

* lock (this) is a problem if the instance can be accessed publicly. * lock (typeof (MyType)) is a problem if MyType is publicly accessible.

Sin embargo, no da un razonamiento sólido para ello. El bloqueo (esto) se explica aquí en SO . Estoy interesado en el caso de bloqueo (typeof (MyType)). ¿Qué es peligroso al respecto?

Gracias.


Es el mismo problema que con el lock(this) : está bloqueando una referencia a la que otro código tiene acceso, por lo que también podría estar bloqueada.

Si tiene dos bloques de código no relacionados bloqueados en la misma referencia sin pretender excluirse mutuamente, entonces, en el mejor de los casos, podría perder un poco de rendimiento debido a la falta de concurrencia, y en el peor de los casos, podría introducir un punto muerto.


Es peligroso porque cualquier cosa puede atrapar ese bloqueo, por lo que es difícil o imposible evitar una situación de punto muerto.

Solía ​​haber un artículo sobre esto ("Do not Lock Type Objects!", Un artículo del Dr. GUI) con algunos comentarios de Rico Mariani. Aparentemente el artículo ya no está disponible directamente, pero hay ''espejos'' flotando, incluso en http://bytes.com/topic/c-sharp/answers/249277-dont-lock-type-objects .

Aquí hay un extracto:

El problema básico aquí es que no posee el objeto tipo, y no sabe quién más podría acceder a él. En general, es una muy mala idea confiar en bloquear un objeto que no creaste y no saber a quién más podría estar accediendo. Hacerlo invita a un punto muerto. La forma más segura es bloquear solo objetos privados.

Pero espera; es incluso peor que todo eso. Resulta que, a veces, los objetos de tipo se comparten entre los dominios de la aplicación (pero no entre los procesos) en las versiones actuales del tiempo de ejecución de .NET. (Esto generalmente está bien ya que son inmutables). Eso significa que es posible que OTRA APLICACIÓN se ejecute incluso en un dominio de aplicación diferente (pero en el mismo proceso) para bloquear su aplicación al obtener un bloqueo en un tipo de objeto que desea bloquear y nunca lo liberaste Y sería fácil acceder a ese tipo de objeto porque el objeto tiene un nombre, ¡el nombre completo del tipo! Recuerda que bloquear / bloques SyncLock (que es una palabra amable para cuelga) hasta que pueda obtener un bloqueo. Obviamente, es bastante malo confiar en un bloqueo que otro programa o componente puede bloquear y provocar un bloqueo.


Esto no sería "un problema" si se siguiera esta forma modificada paralela del consejo:

En general, evite bloquear un tipo público o instancias que no haya creado o definido . El lock (this) construcciones comunes lock (this) , lock (typeof (MyType)) infringe esta directriz si no creó la instancia o no declara el tipo .

Sin embargo, como ''no se puede garantizar'' lo anterior para tipos públicos o instancias accesibles en todos los códigos encontrados, MSDN y otras fuentes argumentan que deben evitarse para la Programación Defensiva frente a un problema singular de tiempo de ejecución difícil de detectar (Interbloqueo) . Este es un buen consejo dado que la mayoría de los codificadores no son muy buenos o diligentes con las reglas.

..y alguien que se encontró con ese error en la naturaleza sería mucho más inflexible en cuanto a no permitir que este problema específico vuelva a ocurrir, al imponer las pautas establecidas. (Java 1.0 / 1.1 con el modelo de UI Threaded AWT fue especialmente problemático).

El caso de lock ("mylock") es singularmente especial en el sentido de que debe evitarse debido a la intercepción de cadenas ya que generalmente no se puede "saber" si están violando los consejos anteriores.


También se indica la documentación bajo el tema "Mejores prácticas administradas para enhebrar". https://msdn.microsoft.com/en-us/library/1c9txz50(v=vs.110).aspx

Dice;

No use tipos como objetos de bloqueo. Es decir, evite el código como el bloqueo (typeof (X)) en C # o SyncLock (GetType (X)) en Visual Basic, o el uso de Monitor.Ingrese con los objetos Type. Para un tipo dado, solo hay una instancia de System.Type por dominio de aplicación. Si el tipo que bloqueas es público, el código que no sea el tuyo puede bloquearlo, lo que lleva a bloqueos . Para problemas adicionales, vea las Reliability Reliability .

Tenga cuidado al bloquear instancias, por ejemplo, bloquear (esto) en C # o SyncLock (Me) en Visual Basic. Si otro código en su aplicación, externo al tipo, bloquea el objeto, podrían producirse interbloqueos .


porque el objetivo de un bloqueo SÓLO es para establecer un lugar donde almacenar el bloqueo booleano (¿Estoy bloqueado o no?) para que otros hilos miran ...

El concepto erróneo de que el objetivo de un bloqueo está de alguna manera bloqueado es simplemente incorrecto ... Lo que está "bloqueado" es, .... nada, a menos que en métodos que pueden acceder a alguna memoria compartida de una manera insegura, escriba el código para ver este bloqueo y no continuar hasta que se haya liberado ... utilizando un objeto Type, ya que un destino de bloqueo es incorrecto porque los fragmentos de código en cualquier parte del proceso completo pueden acceder a ese tipo de objeto y cambiar el bloque de sincronización que el bloqueo booleano se almacena en. La creación de un objeto de ámbito local le permite garantizar mejor que solo los hilos y métodos que pueden acceder o interferir con su memoria compartida "en riesgo" también puedan acceder y / o modificar el bloqueo.