2010-11-01 11 views

Respuesta

12

Imagine una instancia de una clase con una variable global en ella. Imagine que dos hilos llaman a un método en ese objeto exactamente al mismo tiempo, y ese método actualiza la variable global dentro.

La probabilidad es que el valor de la variable se corrompa. Diferentes lenguajes y compiladores/intérpretes tratarán esto de diferentes maneras (o no lo harán en absoluto ...) pero el punto es que obtienes resultados "no deseados" e "impredecibles".

Imagine que el método obtiene un "bloqueo" en la variable antes de intentar leer o escribir en ella. El primer hilo para llamar al método obtendrá un "bloqueo" en la variable, el segundo hilo para llamar al método tendrá que esperar hasta que el primer hilo libere el bloqueo. Mientras todavía tenga una condición de carrera (es decir, el segundo subproceso podría sobrescribir el valor del primero), al menos tiene resultados predecibles porque no hay dos subprocesos (que no se conocen entre sí) que pueden modificar el valor al mismo tiempo.

Utiliza la instrucción lock para obtener ese bloqueo en la variable. Normalmente desea definir una variable objeto separado y el uso que para el objeto de bloqueo:

public class MyThreadSafeClass 
{ 
    private readonly object lockObject = new object(); 
    private string mySharedString; 

    public void ThreadSafeMethod(string newValue) 
    { 
     lock (lockObject) 
     { 
      // Once one thread has got inside this lock statement, any others will have to wait outside for their turn... 
      mySharedString = newValue; 
     } 
    } 
} 

Un tipo se considera "thread-safe" si se aplica el principio de que hay corrupción ocurrirá si los datos compartidos se accede por múltiples hilos al mismo tiempo.

Tenga cuidado con la diferencia entre "inmutable" y "seguro para subprocesos". Thread-safe dice que ha codificado el escenario y no se dañará si dos subprocesos acceden al estado compartido al mismo tiempo, mientras que la inmutabilidad simplemente dice que devuelve un objeto nuevo en lugar de modificarlo. Los objetos inmutables son seguros para subprocesos, pero no todos los objetos seguros para subprocesos son inmutables. código seguro

+0

Entonces, si un tipo es seguro para subprocesos, implementa el bloqueo internamente y no debería volver a implementarlo. ¿Está bien? Gracias Neil. –

+0

Sí, si reutiliza el tipo de otra persona (por ejemplo, desde una biblioteca de terceros) y se anuncia como "seguro para subprocesos", no debería necesitar escribir el 'candado (...) {... } 'declaraciones sobre los usos del mismo. Sin embargo, si está configurando una variable de ese tipo y la variable misma puede ser modificada por diferentes hilos, debe bloquearla. –

7

Thread medios de código que se puede acceder con muchos hilos y todavía funciona correctamente.

En C#, esto normalmente requiere algún tipo de mecanismo de sincronización. Una simple es la declaración lock (que está detrás de escena una llamada al Monitor.Enter). Un bloque de código que está rodeado por un bloque lock solo se puede acceder por un hilo a la vez.

Cualquier uso de un tipo que no sea seguro para subprocesos requiere que usted mismo administre la sincronización.


Un buen recurso para aprender sobre el roscado en C# es el libro electrónico gratis por Joe Albahari, que se encuentra here.

+0

Gracias Oded que fue una gran lectura y lo recomiendo también. –

Cuestiones relacionadas