Me estoy ejecutando en una máquina de 32 bits y puedo confirmar que los valores largos pueden rasgarse usando el siguiente fragmento de código que se ejecuta muy rápido.Simular rasgar un doble en C#
static void TestTearingLong()
{
System.Threading.Thread A = new System.Threading.Thread(ThreadA);
A.Start();
System.Threading.Thread B = new System.Threading.Thread(ThreadB);
B.Start();
}
static ulong s_x;
static void ThreadA()
{
int i = 0;
while (true)
{
s_x = (i & 1) == 0 ? 0x0L : 0xaaaabbbbccccddddL;
i++;
}
}
static void ThreadB()
{
while (true)
{
ulong x = s_x;
Debug.Assert(x == 0x0L || x == 0xaaaabbbbccccddddL);
}
}
Pero cuando intento algo similar con los dobles, no consigo desgarrarme. ¿Alguien sabe por qué? Por lo que puedo decir de la especificación, solo la asignación a un flotador es atómica. La asignación a un doble debe tener un riesgo de desgarro.
static double s_x;
static void TestTearingDouble()
{
System.Threading.Thread A = new System.Threading.Thread(ThreadA);
A.Start();
System.Threading.Thread B = new System.Threading.Thread(ThreadB);
B.Start();
}
static void ThreadA()
{
long i = 0;
while (true)
{
s_x = ((i & 1) == 0) ? 0.0 : double.MaxValue;
i++;
if (i % 10000000 == 0)
{
Console.Out.WriteLine("i = " + i);
}
}
}
static void ThreadB()
{
while (true)
{
double x = s_x;
System.Diagnostics.Debug.Assert(x == 0.0 || x == double.MaxValue);
}
}
Pregunta estúpida: ¿qué es lagrimeo? – Oded
operaciones en ints son garantizadas para ser atómicas en cuanto al acceso por múltiples hilos. No es así con los largos. Lagrimeo consiste en obtener una mezcla de dos valores provisionales (malo). Se pregunta por qué no se ve lo mismo en dobles, ya que los dobles tampoco garantizan las operaciones atómicas. – hatchet
@Oded: en máquinas de 32 bits, solo se escriben 32 bits a la vez. Si escribe un valor de 64 bits en una máquina de 32 bits y escribe en la misma dirección al mismo tiempo en dos hilos diferentes, en realidad tiene * cuatro * escrituras, no * dos *, porque las escrituras se hacen 32 bits en un momento. Por lo tanto, es posible que los hilos corran, y cuando el humo se borre, la variable contiene los 32 bits superiores escritos por un hilo, y los 32 bits inferiores escritos por el otro. Entonces puede escribir 0xDEADBEEF00000000 en un hilo y 0x00000000BAADF00D en otro, y terminar con 0x0000000000000000 en la memoria. –