He leído algo sobre SyncRoot pattern como regla general para evitar interbloqueos. Y al leer una pregunta de hace algunos años (vea esto link), creo que entiendo que algunos usos de este patrón pueden ser incorrectos. En particular, me he centrado en las siguientes frases de this topic:Algunas aclaraciones sobre el patrón SyncRoot: ¿cuál es la forma correcta de usar este patrón?
Se dará cuenta de una propiedad SyncRoot en muchas de las Colecciones en System.Collections. En retrospectiva, creo que esta propiedad fue un error ... Tenga la seguridad de que no cometeremos el mismo error ya que construimos las versiones genéricas de estas colecciones.
De hecho, por ejemplo, List<T>
clase no implementa SyncRoot
propiedad, o más correctamente que se implementa de manera explícita (véase this answer), por lo que debe convertir a ICollection
con el fin de usarlo. Pero this comment argumenta que hacer público un campo privado SyncRoot
es una mala práctica como el bloqueo en this
(ver this answer), como también se confirmó en this comment.
Por lo tanto, si entiendo correctamente, cuando implemente una estructura de datos no segura para subprocesos, ya que podría usarse en un contexto multiproceso, no debería (en realidad, no debo) proporcionar la propiedad SyncRoot
. Pero debería dejar al desarrollador (que usará esta estructura de datos) la tarea de asociarlo con un objeto SyncRoot privado como en el siguiente código de ejemplo.
public class A
{
private MyNonThreadSafeDataStructure list;
private readonly object list_SyncRoot = new object;
public Method1()
{
lock(list_SyncRoot)
{
// access to "list" private field
}
}
public Method2()
{
lock(list_SyncRoot)
{
// access to "list" private field
}
}
}
En resumen, entiende que las mejores prácticas para la sincronización/bloqueo debe ser el siguiente:
- Cualquier objeto SyncRoot privadas no deben ser expuestos a través de una propiedad pública; en otras palabras, una estructura de datos personalizada no debe proporcionar una propiedad pública
SyncRoot
(consulte también this comment). - En general, no es obligatorio utilizar objetos privados para el bloqueo (consulte this answer).
- Si una clase tiene varios conjuntos de operaciones que deben sincronizarse, pero no entre sí, debe tener múltiples objetos SyncRoot privados (consulte this comment).
¿Cuál es el significado del uso adecuado de este patrón?
Mi opinión es que si quieres hacer una clase segura para subprocesos internamente, haces el bloqueo internamente (en privado) y documentas que la clase es segura para subprocesos en general. De lo contrario, haga _no lock_, documente que la clase no es segura para subprocesos, y permita que los consumidores de su clase implementen su propio bloqueo según lo necesiten para su uso específico. –