【发布时间】:2014-04-24 07:27:36
【问题描述】:
眼见为实。任何人都可以重现读取小数点的程序吗?我尝试启动多个线程,在 1 和 2 之间更改相同的小数。我没有捕获任何不同于 1 或 2 的读取。
编辑:我喜欢看到读取器线程看不到写入器线程的原子更改,因此该值应该不同于 1 或 2。
void TornDecimalReadTest()
{
decimal sharedDecimal = 1;
int threadCount = 100;
var threads = new List<Thread>();
for (int i = 0; i < threadCount; i++)
{
int threadId = i;
var thread = new Thread(() =>
{
Thread.Sleep(5000);
decimal newValue = threadId % 2 == 0 ? 1 : 2;
bool isWriterThread = threadId % 2 == 0;
Console.WriteLine("Writer : " + isWriterThread + " - will set value " + newValue);
for (int j = 0; j < 1000000; j++)
{
if (isWriterThread)
sharedDecimal = newValue;
decimal decimalRead = sharedDecimal;
if (decimalRead != 1 && decimalRead != 2)
Console.WriteLine(decimalRead);
}
});
threads.Add(thread);
}
threads.ForEach(x => x.Start());
threads.ForEach(x => x.Join());
}
【问题讨论】:
-
什么是“残缺的小数”?
-
您有一些源代码与我们分享吗?
-
我知道他的意思。他说的是“撕裂读取”,这种情况发生在一个线程中更新一个没有原子读/写操作的值类型,而另一个线程正在读取它,导致值损坏。
-
我建议你选择0M和decimal.MaxValue这两个十进制数。让线程不断地读取和写入这些值,看看你是否在读取时得到一个撕裂的值。 1M 和 2M 的问题是它们的位是相同的,除了最低字节,所以它们永远不会得到一个撕裂的值,因为大多数字节都是“0”。
-
还可以查看这篇 msdn 文章,它有一个关于读/写撕裂的示例:msdn.microsoft.com/en-us/magazine/cc817398.aspx