2010-01-11 11 views
11

¿Es necesario proteger el acceso a una sola variable de un tipo de referencia en una aplicación multiproceso? Actualmente bloqueo esa variable de esta manera:¿Es necesario un bloqueo en esta situación?

private readonly object _lock = new object(); 
private MyType _value; 
public MyType Value 
{ 
    get { lock (_lock) return _value; } 
    set { lock (_lock) _value = value; } 
} 

Pero me pregunto si esto es realmente necesario? ¿La asignación de un valor a un campo no es atómica? ¿Algo puede salir mal si no bloqueo este caso?

P.S .: MyType es una clase inmutable: todos los campos están establecidos en el constructor y no cambian. Para cambiar algo, se crea una nueva instancia y se asigna a la variable anterior.

+4

Supongamos que le pregunté "¿es necesario un candado en una puerta?" Puede responder al señalar que no he descrito la puerta o la tarea que la puerta debe realizar. Se necesita un candado en una puerta si la tarea para la que se inventó la puerta no se puede lograr sin agregar un candado. Nadie puede decirle si la tarea para la que está diseñada su variable se puede lograr sin un bloqueo a menos que le diga cuál es esa tarea. Proporcione una * explicación detallada y completa * de * todos los posibles escenarios de subprocesamiento * en los que se pueda usar la variable, y qué semántica desea que suceda en cada uno. –

Respuesta

10

Ser atómico es raramente suficiente.

Por lo general, quiero obtener el último valor de una variable, en lugar de verla como obsoleta, por lo que se requiere algún tipo de barrera de memoria, tanto para leer como para escribir. Un bloqueo es una forma simple de hacer esto bien, a costa de perder potencialmente algún rendimiento debido a la disputa.

I usó para creer que hacer la variable volátil sería suficiente en esta situación. Ya no estoy convencido de que este sea el caso. Básicamente, ahora trato de evitar escribir código sin candado cuando se trata de datos compartidos, a menos que pueda usar bloques escritos por personas que realmente entienden estas cosas (por ejemplo, Joe Duffy).

+0

tiene razón. mi respuesta no es correcta – Benny

+1

Además, como usted mismo dice en http://www.yoda.arachsys.com/csharp/threads/volatility.shtml, ni siquiera hay garantía de que la asignación sea atómica (depende de la alineación de la memoria) –

+1

@Jon, the " último vs rancio "es un poco nebuloso y no definitivo. Quiero decir, incluso si está completamente bloqueado y protegido, qué valor obtienes con una lectura no depende del comportamiento algo aleatorio del algoritmo de cambio de proceso del sistema operativo ... Podría ejecutar tu hilo de lectura justo antes de la otra escritura "concurrente", o viceversa ... Esta clase de problema está fuera del alcance de lo que generalmente consideramos un problema de multihilo. Si es importante, debe ser administrado con algún otro mecanismo ... ¿no? –

0

todo depende de si se accederá a la propiedad por varios hilos. y se dice que alguna variable es una operación atómica, en este caso de operación atómica, no es necesario usar el bloqueo. lo siento por un inglés pobre.

en tu caso, inmutable, creo que no es necesario el bloqueo.

+2

Si el objeto es inmutable no es relevante. La * variable * es mutable; es por eso que se llaman "variables". –

+0

-1 porque Eric tiene razón. – tony

7

Existe la palabra clave volatile para esto. Si es seguro o no depende del escenario. Pero el compilador puede hacer funny stuff, como reorganizar el orden de operación. Entonces, incluso leer/escribir en un campo puede ser inseguro.

+0

hey, tu enlace a volátil es incorrecto ... –

+0

Mi error. Corregido el enlace. – ewernli

+1

Voy a agregar, sin embargo: 'volátil' no solucionará el problema en todos los casos. –

4

Puede ser un problema. No se trata solo de la tarea en sí misma. Debido al almacenamiento en caché, los subprocesos simultáneos pueden ver una versión anterior del objeto si no se bloquea. Entonces, si un bloqueo es necesario dependerá exactamente de cómo lo use, y usted no lo muestra.

Aquí hay un free, sample chapter of "Concurrent Programming in Windows" que explica este problema en detalle.

+0

No es 'caché'. Es un nuevo orden de instrucciones en los búferes de lectura/escritura pendientes. Similar pero no es lo mismo. Los cachés en la mayoría de las CPU son coherentes. Es el orden en que se escriben los valores incluso en la primera memoria caché. – tony

+0

Tony, tienes razón en que la reescritura de instrucciones está involucrada, y está mal que el almacenamiento en caché no. Con varias CPU, cada una tiene su propia memoria caché, que no se garantiza que sea consistente fuera de un bloqueo. Ver, por ejemplo: http://www.bluebytesoftware.com/blog/2009/10/20/FalseSharingIsNoFun.aspx –

+0

Lo sentimos; link incorrecto. Pruebe http://www.bluebytesoftware.com/blog/2009/05/17/LoadsCannotPassOtherLoadsRevisited.aspx –

Cuestiones relacionadas