¿Cuándo debo usar volátil/Thread.MemoryBarrier() para seguridad de subprocesos?Cuándo utilizar 'volátil' o 'Thread.MemoryBarrier()' en el código de bloqueo de seguridad de hilo? (C#)
Respuesta
Usted usa volatile
/Thread.MemoryBarrier()
cuando quiere acceder a una variable entre subprocesos sin bloquear.
Las variables que son atómicas, como por ejemplo int
, siempre se leen y escriben completas a la vez. Eso significa que nunca obtendrás la mitad del valor antes de que otro hilo lo cambie y la otra mitad después de que haya cambiado. Por eso, puede leer y escribir de forma segura el valor en diferentes hilos sin sincronizar.
Sin embargo, el compilador puede optimizar algunas lecturas y escrituras, lo que previene con la palabra clave volatile
.Si, por ejemplo, tiene un bucle de esta manera:
sum = 0;
foreach (int value in list) {
sum += value;
}
El compilador puede realmente hacer los cálculos en un registro del procesador y sólo escribir el valor de la variable sum
después del bucle. Si crea la variable sum
volatile
, el compilador generará un código que leerá y escribirá la variable para cada cambio, de modo que su valor esté actualizado en todo el ciclo.
¿Qué hay de malo en
private static readonly object syncObj = new object();
private static int counter;
public static int NextValue()
{
lock (syncObj)
{
return counter++;
}
}
?
Esto hace todo el bloqueo necesario, barreras de memoria, etc. para usted. Está bien entendido y es más legible que cualquier código de sincronización personalizado basado en volatile
y Thread.MemoryBarrier()
.
EDITAR
No puedo pensar en un escenario en el que me gustaría usar volatile
o Thread.MemoryBarrier()
. Por ejemplo
private static volatile int counter;
public static int NextValue()
{
return counter++;
}
es no equivalente al código de arriba y es no thread-safe (volatile
no hace ++
mágicamente convertido thread-safe).
En un caso como este:
private static volatile bool done;
void Thread1()
{
while (!done)
{
// do work
}
}
void Thread2()
{
// do work
done = true;
}
(que deberían funcionar) que haría uso de un ManualResetEvent para indicar cuándo se realiza Thread2.
Nada 'incorrecto' con su código. Estoy tratando de comprender las circunstancias en las que se aplican los volatiles y MemoryBarrier. Como en la respuesta de Jon Skeet aquí: http://stackoverflow.com/questions/395232/we-need-to-lock-a-net-int32-when-reading-it-in-a-multithreaded-code. – Alex
.net también tiene un modelo de memoria bastante estricto, como leer o escribir no puede seguir otra escritura. –
Aunque la especificación ECMA tiene un modelo de memoria bastante débil, por lo que es posible que desee tener cuidado con eso, consulte http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx y http: // blogs .msdn.com/cbrumme/archive/2003/05/17/51445.aspx –
Básicamente, si está utilizando cualquier otro tipo de sincronización para hacer que su código sea enhebrable, entonces no es necesario.
La mayoría de los mecanismos de bloqueo (incluido el bloqueo) implican automáticamente una barrera de memoria para que múltiples procesadores puedan obtener la información correcta.
Volatile y MemoryBarrier se utilizan principalmente en escenarios sin bloqueo en los que se intenta evitar la penalización de rendimiento del bloqueo.
Editar : Debe leer this article por Joe Duffy sobre el modelo de memoria CLR 2.0, que aclara muchas cosas (si está realmente interesado debe leer toda el artículo de Joe Duffie que es el más grande de persona experta en el paralelismo en .NET)
+1, pero así está absolutamente claro. Si haces lo que hace dtb, no es necesario volátil/Thread.MemoryBarrier. También hay situaciones en las que la volatilidad sola en un miembro no es suficiente. – Skurmedel
Como el nombre implica garantías volátiles, el valor de caché se vacía en la memoria para que todos los subprocesos vean el mismo valor. Por ejemplo, si tengo un número entero cuya última escritura se guarda en el caché, es posible que otros hilos no lo vean. Incluso pueden ver su copia en caché de ese entero. Marcar una variable como volátil hace que se lea directamente desde la memoria.
Sriwantha Sri Aravinda Attanayake
- 1. volátil y Thread.MemoryBarrier en C#
- 2. ¿Cuándo usar el hilo de bloqueo en C#?
- 3. Pautas de cuándo utilizar el bloqueo
- 4. entendimiento sincronización de hilos de bloqueo y no Thread.MemoryBarrier
- 5. C# elementos de matriz volátil?
- 6. Seguridad de hilo C# con get/set
- 7. ¿Es 'volátil' necesario en este código C++ multihilo?
- 8. C de seguridad # hilo de parámetros de configuración globales
- 9. Hilo de seguridad memoization
- 10. ¿Cuándo se debe usar la palabra clave volátil en C#?
- 11. bloqueo intrínseco de hilo
- 12. Al utilizar el bloqueo contra MemoryBarrier en .NET
- 13. Hilo de seguridad en F #
- 14. ContainsKey hilo de seguridad
- 15. C++ variables de subprocesamiento volátil
- 16. Cuándo utilizar punteros en C++
- 17. EventHandler <TEventArgs> seguridad de hilo en C#?
- 18. Modelo de memoria C# y variable no volátil inicializada antes de la creación del otro hilo
- 19. ¿Qué hilo obtendrá el bloqueo?
- 20. Llamando al código de Python desde un hilo en C
- 21. Cuándo utilizar pathParams o QueryParams
- 22. hilo de seguridad con diccionario
- 23. preprocesador de C# - Código de bloqueo para el diseñador XAML
- 24. Cuándo utilizar!() O! = Cuando, si no nula
- 25. ¿Cuánta seguridad de hilo es demasiado?
- 26. Volátil: por qué prevenir el código de reordenación del compilador
- 27. Cuándo utilizar el operador "^"
- 28. Objective-C - Cuándo utilizar 'auto'
- 29. ¿Es este un uso correcto de Thread.MemoryBarrier()?
- 30. operaciones atómicas Hilo de seguridad en gcc
+1, pero ¿en qué escenarios importa que el compilador genere código que lea y escriba la variable para cada cambio? – dtb
Eso se desea principalmente al enhebrar dtb, si no un hilo puede tener un valor diferente al del otro y pueden ocurrir todo tipo de locuras. – Skurmedel
Bueno, eso o usa una barrera de memoria. – Skurmedel