Tôi đang chạy trên máy 32 bit và tôi có thể xác nhận rằng các giá trị dài có thể xé bằng đoạn mã sau đây truy cập rất nhanh.Mô phỏng xé đôi trong 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);
}
}
Nhưng khi tôi thử một thứ gì đó tương tự như tăng gấp đôi, tôi không thể bị xé rách. Có ai biết tại sao không? Theo như tôi có thể nói từ spec, chỉ gán cho một phao là nguyên tử. Việc giao cho một đôi nên có nguy cơ rách.
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);
}
}
Câu hỏi ngu ngốc - rách là gì? Các hoạt động – Oded
trên int được đảm bảo là nguyên tử liên quan đến truy cập bởi nhiều luồng. Không phải như vậy với longs. Tearing là nhận được một kết hợp của hai giá trị tạm thời (xấu). Anh ấy tự hỏi tại sao giống nhau không được nhìn thấy trong đôi, kể từ khi tăng gấp đôi cũng không đảm bảo hoạt động nguyên tử. – hatchet
@Oded: Trên máy 32 bit, chỉ có 32 bit được ghi tại một thời điểm. Nếu bạn đang viết một giá trị 64 bit trên một máy 32 bit, và ghi vào cùng một địa chỉ cùng một lúc trên hai luồng khác nhau, bạn thực sự có * bốn * ghi, chứ không phải * hai *, vì ghi được thực hiện 32 bit tại một thời gian. Do đó có thể cho các chủ đề để chạy đua, và khi khói xóa biến chứa 32 bit hàng đầu được viết bởi một sợi, và 32 bit dưới cùng được viết bởi một luồng khác. Vì vậy, bạn có thể viết 0xDEADBEEF00000000 trên một sợi và 0x00000000BAADF00D trên một sợi khác và kết thúc với 0x0000000000000000 trong bộ nhớ. –