32 비트 시스템에서 실행 중이며 매우 빠르게 실행되는 다음 코드 스 니펫을 사용하여 긴 값을 찢을 수 있는지 확인할 수 있습니다. 나는 복식과 비슷한 때C에서 double을 시뮬레이트합니다.
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);
}
}
는하지만, 나는 어떤 찢어를 얻을 수 아니에요. 아무도 이유를 아나요? 내가 사양에서 알 수있는 한, float에 대한 할당 만이 원자 적입니다. 두 배로의 할당은 찢어 질 위험이 있습니다.
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);
}
}
어리석은 질문 - 무엇이 찢어지고 있습니까? – Oded
int에 대한 연산은 다중 스레드에 의한 액세스와 관련하여 원자 적이어야합니다. 그럴 수는 없습니다. 찢어지고 두 개의 중간 값 (나쁜)이 혼합됩니다. 그는 복식이 원자 조작을 보장하지 않기 때문에 복식에서 왜 같은 것이 보이지 않는지 궁금해합니다. – hatchet
@Oded : 32 비트 컴퓨터에서는 한 번에 32 비트 만 씁니다. 32 비트 컴퓨터에서 64 비트 값을 쓰고 동시에 두 개의 다른 스레드에서 같은 주소에 쓰는 경우 쓰기는 32 비트에서 수행되기 때문에 * 2 *가 아닌 * 4 개의 쓰기가 실제로 있습니다. 시간. 따라서 스레드가 경쟁 할 수 있으며 연기가 없어지면 변수는 한 스레드에서 쓰여진 상위 32 비트와 다른 스레드에서 쓰여진 하위 32 비트를 포함합니다. 따라서 한 스레드에는 0xDEADBEEF00000000을 쓰고 다른 스레드에는 0x00000000BAADF00D를 쓰고 메모리에는 0x0000000000000000으로 끝낼 수 있습니다. –