2011-04-15 18 views
5

Estaba buscando un patrón para poder proporcionar una versión segura e insegura de subprocesos de la misma clase. Los aspectos técnicos de esto son bastante obvios. Supongo que estaba esperando a encontrar las convenciones de nombres/de acceso, etc ...¿Cuál es el beneficio de este .Net patrón

Así que descubro este patrón en todas partes del espacio de nombres '' Systems.Collections:

public class WhatEv 
{ 
    private class SyncWhatEv : WhatEv 
    { 
     // overrides IsSyncronized = true 
     // overrides whatever else to make it thread safe 
    } 

    public virtual bool IsSynchronized 
    { 
     get { return false; } 
    } 

    public static WhatEv Synchronized(WhatEv whatEv) 
    { 
     return new SyncWhatEv(whatEv); 
    } 
} 

Hay una serie de clases que implementan la siguiente: HashTable, Queue, ArrayList, Stack, etc ... Comprendo la herencia. Pero ¿por qué convertirlo en una clase privada anidada y hacer que el usuario salte a través de un aro para llegar a ella? ¿Hay algún beneficio al hacerlo de esta manera?

+0

Gracias por su contribución hasta ahora. Solo estoy tratando de imaginar un escenario donde el usuario de este quiere recibir la clase base sin saber que es seguro para subprocesos. Si el receptor es un hilo, debería requerir la versión de hilo seguro, ¿verdad? si el receptor no lo es, ¿por qué le importaría? – TBone

+0

Si va a acceder desde dos subprocesos, los dos necesitan estar usando la misma instancia sincronizada. No puede simplemente hacer que el receptor use una instancia sincronizada, y el hilo principal use la versión no sincronizada. Entonces, si hay alguna posibilidad de que otro subproceso acceda al objeto, debe estar sincronizado. Pero vea la respuesta de Joel para un posible problema. – CodeNaked

+0

@Naked - De acuerdo. Pero SyncWhatEv hereda WhatEv. Por lo tanto, la misma instancia de SyncWhatEv podría utilizarse en el hilo principal como tipo WhatEv y requerida por el hilo de trabajo como tipo SyncWhatEv. Solo que esto no es posible porque SyncWhatEv es privado. Actualmente, el hilo debería verificar doblemente IsSynchronized y throw if false. – TBone

Respuesta

-1

Después de reflexionar sobre esto para el fin de semana, y después de no obtener más respuestas. He decidido que la respuesta es: MS estar loco todos ustedes. El objetivo de ofrecer una versión sincronizada del objeto es para la seguridad del hilo, pero un hilo no tiene manera en el tiempo de compilación de requerir una versión segura para el hilo del objeto. La validación de este objeto debe tener lugar en tiempo de ejecución, lo cual es ... falso.

Gracias a todos por su contribución. Lo aprecio.

+0

Encantador. A -1 sin razón. Si no estoy en lo correcto, entonces muéstrame cómo me equivoco. – TBone

3

En la mayoría de los casos, no es necesaria una versión segura para subprocesos del objeto (es decir, Hashtable, Queue). Por lo tanto, no tiene sentido agregar la sobrecarga necesaria para que sea seguro para subprocesos de forma predeterminada. El uso del método Sincronizado permite a los usuarios que necesitan seguridad de subprocesos obtener una versión segura para subprocesos.

La versión sincronizada del objeto no agrega ninguna funcionalidad adicional, salvo la seguridad de la hebra. No exponen a ningún miembro nuevo, ni el hecho de conocer su tipo subyacente realmente ayuda. Entonces se hacen privados y simplemente "se ven" como su clase pública/base.

+0

Si va a costar la creación de una versión segura para hilos, ¿por qué no prescindir de la versión no segura y solo mantener una versión? – BenCr

+0

@BenCr - Debido a que hay un impacto en el rendimiento para garantizar la seguridad del hilo. Como dije, en general, la mayoría de los casos no necesitan seguridad de hilo, pero está ahí cuando lo haces. Además, de la forma en que la mayoría está codificada, generalmente se puede arreglar algo en, por ejemplo, Hashtable y también se puede solucionar en la versión privada segura para subprocesos. Como a este último solo le interesa garantizar que se obtengan los bloqueos adecuados. – CodeNaked

+0

@BenCr, escuché lo que estás diciendo. No soy demasiado paranoico con el costo de rendimiento de un candado, pero mi clase es algo que podría usarse ampliamente en un contexto de un solo hilo y ocasionalmente en un contexto enhebrado (como la mayoría de esas clases, estoy seguro). Parece excesivo tener todo el bloqueo cuando el 90% del tiempo no es necesario. – TBone

2

En teoría, esta es una buena idea, y @CodeNaked tiene una buena explicación. En la práctica, todavía hay problemas con esto. Por ejemplo, si necesita realizar 2 llamadas en su clase de seguridad de subprocesos y necesita seguridad de subprocesos para ambas llamadas combinadas, aún necesita hacer un bloqueo. Buena explicación en este elemento SO: In C# would it be better to use Queue.Synchronized or lock() for thread safety?

+0

Excelente enlace. Estoy de acuerdo en que hacer el bloqueo es una forma más refinada de ir. Sigo pensando que, como patrón, simplemente no tiene sentido para mí. – TBone

Cuestiones relacionadas