眼见为实。任何人都可以重现读取撕裂的小数的程序吗?我尝试旋转多个线程,在 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());
}
这段代码将展示一个撕裂的阅读Decimal
:
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
void run()
{
Task.Run((Action) setter);
Task.Run((Action) checker);
Console.WriteLine("Press <ENTER> to stop");
Console.ReadLine();
}
void setter()
{
while (true)
{
d = VALUE1;
d = VALUE2;
}
}
void checker()
{
for (int count = 0;; ++count)
{
var t = d;
if (t != VALUE1 && t != VALUE2)
Console.WriteLine("Value is torn after {0} iterations: {1}", count, t);
}
}
static void Main()
{
new Program().run();
}
Decimal d;
const Decimal VALUE1 = 1m;
const Decimal VALUE2 = 10000000000m;
}
}
它在发布版本中比在调试版本中发生得更快。
我认为您在测试代码中没有看到撕裂读取的原因是因为您只更改了 0 和 1 之间的值。测试期间更改的位很可能都在用于存储的同一个字中内部的值,并且对单词的访问是原子的。
通过更改 1 到 10000000000 之间的值,我们强制在两个不同的字中更改位,从而可以观察到撕裂的读取。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)