2010-11-02 17 views
11

He hecho una pregunta mal aquí Lock on a variable in multiple threads así que para mayor claridad la voy a preguntar aquí y espero poder preguntarla correctamente.Cómo bloquear una variable utilizada en múltiples hilos

classA 
    creates instance of classB 
    has methodA that can update & uses classB's myVar 
    has methodB that can update & uses classB's myVar 

classB 
    has a variable myVar 

methodA y methodB se pueden ejecutar en subprocesos separados (denominados en nuevos subprocesos desde main). ¿Cómo me aseguro de que esto sea seguro para subprocesos?

+2

Según su otra pregunta, debe describir la situación desde un nivel superior porque realmente parece que va en la dirección incorrecta. –

Respuesta

17

Utilice la palabra clave lock para guardar el código que se puede ejecutar simultáneamente por más de un hilo.

public class ClassA 
{ 
    private ClassB b = new ClassB(); 

    public void MethodA() 
    { 
    lock (b) 
    { 
     // Do anything you want with b here. 
    } 
    } 

    public void MethodB() 
    { 
    lock (b) 
    { 
     // Do anything you want with b here. 
    } 
    } 
} 

Es importante señalar que lock no guarda o bloquear la instancia del objeto utilizado en el comunicado. En cambio, el objeto se utiliza como una forma de identificar una sección de código que se debe impedir que se ejecute si otra sección utilizando la instancia del objeto misma ya se está ejecutando. En otras palabras, se puede utilizar cualquier instancia de objeto que te gusta en las declaraciones lock y todavía sería seguro para acceder a los miembros de ClassB.

0

Mira la documentación lock comunicado.

0

ClassB no debe exponer una variable (por lo que probablemente se refiera a un miembro de datos). Exponga una propiedad o un conjunto de métodos en su lugar, y use ReaderWriterLockSlim para manejar múltiples hilos.

+0

Recomendación para que la clase es prematura dada la escasez de información en las preguntas, imo –

+0

Puede (y debe) hacer sus propios puntos de referencia, pero creo que se dará cuenta de que 'ReaderWriterLockSlim' será hasta 5 veces más lento que un simple y llano' lock' en este caso. –

0

La solución más sencilla: no comparten la instancia de ClassB entre sus hilos.

En otras palabras, una instancia de un nuevo ClassB con su declaración de hilo y enviarlo como un parámetro.

3

He escrito un blog post de tener múltiples hilos añadir valores a una lista y utilizando lock() para evitar las escrituras colisione con qué esto tiene que ser hecho.

1

Por desgracia, la cuestión es algo ambiguo sobre lo que se considera éxito en términos de seguridad de los subprocesos. La seguridad del subproceso solo significa que la operación funcionaría correctamente si se están ejecutando varios subprocesos.

Lo que parece ser que falta es si classA.methodA o classA.methodB necesita terminar su operación con classB.myVar antes de cualquier otro hilo llamando a classA.methodA (...) o classA.methodB (...) Determinaría qué tipo de patrón de bloqueo necesitaría.

Por ejemplo, si necesita una garantía en la lectura de un valor, que se vería como la siguiente:

public class classA 
{ 
    private classB b = new classB(); 

    public void methodA() 
    { 
     lock (b) 
     { 
      // Operation without calling methodA() or methodB() 
      // Read b.myVar 
      // Update b.myVar 
     } 
    } 

    public void methodB() 
    { 
     lock (b) 
     { 
      // Operation without calling methodA() or methodB() 
      // Read b.myVar 
      // Update b.myVar 
     } 
    } 
} 

En otro ejemplo, si b.myVar es algún tipo de colección que necesita ser sincronizado como un caché, se vería así:

public class classA 
{ 
    private classB b = new classB(); 

    public void methodA() 
    { 
     // Read b.myVar for missing collection item 

     lock (b) 
     { 
      // Check for missing collection item again. If not missing, leave lock 
      // Operation without calling methodA() or methodB() 
      // Read b.myVar 
      // Update b.myVar with new array item 
     } 
    } 

    public void methodB() 
    { 
     // Read b.myVar for missing collection item 
     lock (b) 
     { 
      // Check for missing collection item again. If not missing, leave lock 
      // Operation without calling methodA() or methodB() 
      // Read b.myVar 
      // Update b.myVar with new array item 
     } 
    } 
} 
+0

El segundo bloque de código no es seguro. Una lectura de 'b.myVar' podría ocurrir simultáneamente con una escritura en' b.myVar' si intenta realizar la lectura fuera del bloqueo. –

Cuestiones relacionadas