2009-10-23 19 views
10

En mi aplicación multihilo estoy usando algunas variables que pueden ser alteradas por muchas instancias al mismo tiempo. Es extraño, pero funcionó bien sin ningún problema ... pero, por supuesto, necesito hacerlo seguro para subprocesos. Estoy empezando con cerraduras, por lo que agradecería su consejo:¿Bloquear propiedades, buen enfoque?

Cuando el cliente se conecta, se crea la clase Cliente donde cada Cliente tiene su propia variable "A".

A veces, el cliente llama al método así:

Client selectedClient SelectOtherClientClassByID(sentID); 

selectedClient.A=5; 

No hay problemas hasta ahora con que incluso cuando 5 clases estaban haciendo al mismo tiempo (subprocesos), pero yo estaba pensando ¿qué pasa con la adición de cerraduras para conocer el inmueble ?

igual:

A { 
    get { return mA; } 
    set { 
     // use lock here for settting A to some value 
    }  
} 

¿Estaría bien?

Respuesta

16

Necesita usar bloqueos en TANTO obtener y establecer. Este bloqueo debe ser el mismo objeto. Por ejemplo:

private object mylock = new object(); 

public int A { 

    get { 
    int result; 
    lock(mylock) { 
    result = mA; 
    } 
    return result; 
    } 

    set { 
    lock(mylock) { 
     mA = value; 
    } 
    } 
} 
+1

Gracias ... por cierto para leer Es porque podría cambiar durante la lectura por otra clase? – Petr

+1

No es una buena idea bloquear esto, ya que es accesible desde fuera del tipo. –

+0

Podría cambiar mientras configuras. El bloqueo actúa como una barrera, impidiendo cualquier otra acción hasta que el propietario del candado suelta el candado. –

2

Es muy raro cuando todo lo que necesita es simplemente configurar una sola propiedad. Más a menudo selectedClient.A = 5 será una parte de una operación lógica mucho más grande, que implica varias asignaciones/evaluaciones/etc. Durante toda esa operación, prefiere selectedClient para estar en un estado constante y no introducir condiciones de bloqueo/carrera. Por lo tanto, será mucho mejor para exponer SyncRoot propiedad en su clase Client y bloqueo en que a partir del código de llamada:

Client selectedClient = GetClient(...); 

lock(selectedClient.SyncRoot) 
{ 
    selectedClient.A = 5; 
    selectedClient.B = selectedClient.A * 54; 
} 
+0

No tengo otras variables compartidas que una lista y esas int. Principalmente, no sé nada sobre SyncRoot aún :) – Petr

+0

No se recomienda SyncRoot: Consulte http://blogs.msdn.com/brada/archive/2003/09/28/50391.aspx –

+0

@_NT: Citando de la publicación del blog: "Tenga la seguridad de que no cometeremos el mismo error al construir las versiones genéricas de estas colecciones."Y aquí estamos, 6 años después, con la Lista . SyncRoot sin notas desalentadoras en MSDN: http://msdn.microsoft.com/en-us/library/bb356596.aspx –

6

Bloqueo de acceso a las propiedades dentro de descriptores de acceso puede dar lugar a resultados falsos. Para el ejemplo, mira el siguiente código:

class C { 
    private object mylock = new object(); 

    public int A { 

     get { 
     int result; 
     lock(mylock) { 
     result = mA; 
     } 
     return result; 
     } 

     set { 
     lock(mylock) { 
      mA = value; 
     } 
     } 
    } 
} 
C obj = new C; 
C.A++; 

(sí, he copiado desde la primera respuesta) Hay una condición de carrera aquí! La operación "C.A ++" en realidad requiere dos accesos separados a A, uno para obtener el valor y el otro para establecer el valor actualizado. Nada garantiza que estos dos accesos se llevarán a cabo juntos sin un cambio de contexto entre ellos. Escenario clásico por condición de carrera!

Entonces, ¡cuidado! No es una buena idea colocar cerraduras en los accesos, las cerraduras deben obtenerse explícitamente, como sugiere la respuesta anterior (aunque no tiene que ser con SyncRoots, cualquier objeto servirá)

+0

También me refiero a agregar manualmente el objeto de bloqueo a todas las llamadas en el código Supongo que hay al menos 20 lecturas y 15 escritos en mi código hasta ahora. – Petr

+0

Para hacerlo, expanda su bloqueo para cubrir toda la región crítica. t haz A ++. –

+0

NT: probablemente no te entiendo bien. Tengo alrededor de 15 métodos con diferentes operaciones con esa variable en diferentes instancias. No estoy seguro de cómo te refieres a expandir el loc k. Entonces el bloqueo de propiedades no es bueno si leo correctamente todo lo anterior – Petr