Я запускаюсь на 32-битной машине, и я могу подтвердить, что длинные значения могут разорвать, используя следующий фрагмент кода, который очень быстро ударяет.
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);
}
}
Но когда я пытаюсь что-то подобное с удвоениями, я не могу разрывать. Кто-нибудь знает, почему? Насколько я могу судить по спецификации, только присвоение поплавка является атомарным. Назначение двойнику должно иметь риск разрыва.
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);
}
}