2011-12-28 12 views
8

Me confundí en volatile para el tipo de referencia.volátil para el tipo de referencia en .net 4.0

Entiendo que para el tipo primitivo, volatile puede reflejar los cambios de valor de otra secuencia inmediatamente. Para el tipo de referencia, puede reflejar los cambios de dirección de forma inmediata. Sin embargo, ¿qué pasa con el contenido del objeto? ¿Todavía están en la memoria caché?

(Suponiendo List.Add() es una operación atómica)

Por ejemplo, tengo:

class A 
{ 
    volatile List<String> list; 
    void AddValue() 
    { 
     list.Add("a value"); 
    } 

} 

Si un hilo llama a la función AddValue, la dirección de la lista no cambia, será otro hilo se actualizan sobre el cambio de "contenido" de la lista, o el contenido puede ser almacenado en caché para cada hilo y no se actualiza para otros hilos?

+0

No estoy seguro de esto, pero supongo que dado que la lista es solo un puntero (dirección), cuando el contenido se actualiza se refleja inmediatamente en todas partes, ya que el contenido residiría en el montón, sin embargo, con cambio de direcciones, la pila ha cambiado, y creo que puede residir en un único núcleo. Pero, como dije, no hay experto. Es solo una suposición. – Alxandr

+0

Además, como nota al margen. volátiles volátiles de muchas optimizaciones. MUCHAS optimizaciones. Algunos recomiendan encarecidamente no usar modificadores volátiles, sino usar volatileread y volatilewrite cuando sea necesario (algunos métodos globales estáticos encontrados en una clase en el espacio de nombres del sistema, probablemente se encuentren en google). – Alxandr

+1

@Alxandr: ten cuidado. La lectura volátil y la escritura volátil son métodos potencialmente costosos para llamar e inducen * vallas completas *, no las medias vallas que uno esperaría. Si está escribiendo código sin bloqueo por motivos de rendimiento (¿y qué otra razón tendría para hacer esta locura?) Es muy posible que VolatileRead y VolatileWrite sean peores. Tienes que perfilarlo cuidadosamente. –

Respuesta

2

La palabra clave volatile no tiene ningún impacto en el contenido de la lista (o, más precisamente, el objeto al que se hace referencia).

hablar de actualizan/no actualizada para otro hilo es una simplificación excesiva de lo que está pasando. Debe usar la instrucción lock para sincronizar el acceso a la lista compartida. De lo contrario, estás enfrentando efectivamente condiciones de carrera que pueden llevar a la falla del programa. La clase List<T> no es segura para subprocesos por sí misma.

6

Es peor que eso.

Si accede de forma simultánea a un objeto que no es seguro para subprocesos, es posible que su programa se bloquee. Obtener información desactualizada no es el peor resultado posible.

Al compartir objetos de biblioteca de clase base .NET entre subprocesos, realmente no tiene más remedio que usar el bloqueo. Para la programación sin bloqueos, necesita cambios invasivos a sus estructuras de datos en los niveles más bajos.

19

entiendo que para el tipo primitivo, volátil puede reflejar los cambios de valor de otro hilo inmediatamente

Usted entiende incorrectamente en al menos tres formas. No intente usar volátiles hasta que comprenda a fondo todo sobre modelos de memoria débil, semántica de adquisición y liberación y cómo afectan su programa.

En primer lugar, tenga en claro que la volatilidad afecta a variables, no valores.

En segundo lugar, volátil no afecta las variables que contienen valores de tipos de valores de manera diferente que afecta a las variables que contienen referencias.

Tercero, volátil no significa que los cambios de valor de otros subprocesos son visibles inmediatamente. Volátil significa que las variables tienen adquisición y release semántica. La volatilidad afecta a el orden en que se pueden observar los efectos secundarios de las mutaciones en la memoria a partir de un hilo en particular.La idea de que existe un orden universal coherente de mutaciones y que esas mutaciones en ese orden pueden observarse instantáneamente desde todos los hilos no es una garantía hecha por el modelo de memoria.

Sin embargo, ¿qué ocurre con el contenido del objeto?

¿Qué hay? La ubicación de almacenamiento a la que hace referencia una variable volátil de tipo de referencia no necesita tener características de subprocesamiento particulares.

Si un hilo llama a la función AddValue, la dirección de la lista no cambia, se actualizará otro hilo sobre el cambio de "contenido" de la lista.

Nop. ¿Por qué lo haría? Ese otro hilo podría estar en un procesador diferente, y ese caché del procesador podría haber precargado la página que contiene la dirección de la matriz que está respaldando la lista. La modificación de la lista puede haber cambiado la ubicación de almacenamiento que contiene la dirección de la matriz para hacer referencia a una ubicación completamente diferente.

Por supuesto, la clase de lista no es insegura desde el principio. Si no estás bloqueando el acceso a la lista, entonces la lista simplemente puede bloquearse y morir cuando tratas de hacerlo.

No necesita volátiles; lo que necesita es colocar bloqueos de hilo alrededor de los accesos a la lista. Como las cerraduras de rosca inducen vallas completas, no debería necesitar medias vallas introducidas por volátiles.

+0

Muchas gracias Eric. Según mi comprensión de su explicación, volátil se usa para prevenir los efectos secundarios de las mutaciones de la memoria. Sin embargo, lo que se utiliza para evitar la copia de registro de la CPU del valor de la memoria. En la CPU multi-core, dos núcleos almacenan en caché dos copias de la variable (por ejemplo, una int), si una de ellas la actualiza, ¿cómo la obtendrá el otro? ¿Necesitamos hacer algo en el código C# o automáticamente se ocupa de .net? THnaks de nuevo. – Frank

+1

@Feng: Me has malentendido. No dije que "volátil" previene los efectos secundarios de las mutaciones de la memoria; ¿cómo demonios podría hacer eso? Por el contrario, "volátil" afecta el * orden * en el que posiblemente se puedan * observar * las mutaciones. Lo hace al inducir a adquirir y liberar semántica en lecturas y escrituras variables. ** Si no comprende cómo funciona la semántica de adquisición y liberación, entonces no debe usar volátiles. ** Por supuesto, también desactiva las optimizaciones del almacenamiento en caché. –

1

Consulte http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword para obtener una buena explicación acerca de qué es lo que realmente hace volátil y cómo afecta a los campos.

Toda la parte de enhebrar en ese sitio es obligatoria, de todos modos contiene gran cantidad de información útil que me ha resultado muy útil cuando estaba diseñando un software de subprocesos múltiples.