C# 用c语言再现十进制数的读取
眼见为实。有人能复制一个读取小数点的程序吗?我尝试旋转多个线程,在1和2之间更改相同的十进制数。我没有发现任何与1或2不同的读数C# 用c语言再现十进制数的读取,c#,atomic,lock-free,C#,Atomic,Lock Free,眼见为实。有人能复制一个读取小数点的程序吗?我尝试旋转多个线程,在1和2之间更改相同的十进制数。我没有发现任何与1或2不同的读数 void TornDecimalReadTest() { decimal sharedDecimal = 1; int threadCount = 100; var threads = new List<Thread>(); for (int i = 0; i < thread
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());
}
编辑:我希望读线程看不到写线程的原子变化,因此值应该不同于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());
}
此代码将演示十进制数的读取: 它在发布版本中发生的速度比调试版本快 我认为您在测试代码中没有看到撕裂读取的原因是因为您只更改了0和1之间的值。测试期间更改的位很可能都在用于内部存储值的同一个字中,并且对字的访问是原子的
通过在1和1000000000之间更改值,我们强制位在两个不同的字中更改,从而允许观察到撕裂读取。此代码将演示十进制的撕裂读取: 它在发布版本中发生的速度比调试版本快 我认为您在测试代码中没有看到撕裂读取的原因是因为您只更改了0和1之间的值。测试期间更改的位很可能都在用于内部存储值的同一个字中,并且对字的访问是原子的
通过在1和1000000000之间更改值,我们强制位在两个不同的字中更改,从而允许观察到撕裂的读取。什么是撕裂的十进制数?您有一些源代码与我们共享吗?我知道他的意思。他所说的是读取损坏,当一个线程中更新了一个没有原子读/写操作的值类型,而另一个线程正在读取它时,会发生这种情况,从而导致值损坏。我建议您选择两个十进制数0M和decimal.MaxValue。让线程不断地读写这些值,看看你是否在读的时候得到了一个撕裂的值。1M和2M的问题是,它们的位除了最低的字节外是相同的,因此它们永远不会得到一个撕裂的值,因为大多数字节都是0。另外,看看这篇msdn文章,它有一个关于读/写撕裂的示例:什么是撕裂的十进制数?你有一些源代码与我们分享吗?我知道他的意思。他所说的是读取损坏,当一个线程中更新了一个没有原子读/写操作的值类型,而另一个线程正在读取它时,会发生这种情况,从而导致值损坏。我建议您选择两个十进制数0M和decimal.MaxValue。让线程不断地读写这些值,看看你是否在读的时候得到了一个撕裂的值。1M和2M的问题是,它们的位除了最低的字节外都是相同的,因此它们永远不会得到一个被撕碎的值,因为大多数字节都是0。也请查看这篇msdn文章,它有一个关于读/写撕裂的示例:我刚刚用Int64和0x0000000000000000和0xFFFFFFFFFFFFFF值尝试了相同的实验,但也无法重新生成撕裂。我可以使用0x1234567890ABCDEF和0xFEDCBA0987654321。这也是因为单词是原子的吗?@BanksySan是的,当运行64位代码时,64位整数值的读写是原子的。@MatthewWatson就是这样。“如果增强32位模式,它应该可以工作。”马修沃森刚刚测试过它。如果我将/platform:x86开关添加到编译器中,那么测试就可以运行了!我刚刚用Int64和0x0000000000000000和0xFFFFFFFFFFFFFFFF的值做了同样的实验,但也无法恢复撕裂。我可以使用0x1234567890ABCDEF和0xFEDCBA0987654321。这也是因为单词是原子的吗?@BanksySan是的,当运行64位代码时,64位整数值的读写是原子的。@MatthewWatson就是这样。“如果增强32位模式,它应该可以工作。”马修沃森刚刚测试过它。如果我将/platform:x86开关添加到编译器中,那么测试就可以运行了!