我正在研究着名的'C#in a Nutshell'中的c#threading,在调查Thread.MemoryBarrier()现象时,当我偶然发现Brian在Why we need Thread.MemoryBarrier()?上的例子时,我吓死了。
我有i-7 8700K处理器和4.6.1 .NET,我设法重现问题(程序永远不会结束),即使程序中有以下更改:
class Program
{
static bool stop = false;
public static void Main(string[] args)
{
var t = new Thread(() =>
{
Console.WriteLine($"Thread begin");
bool toggle = false;
//while (true)
while (!stop)
{
if (stop)
{
break;
}
toggle = !toggle;
}
Console.WriteLine($"Thread end");
});
t.Start();
Thread.Sleep(1000);
stop = true;
Console.WriteLine($"Stop flag set. Waiting for thread to end...");
t.Join();
Console.ReadKey();
}
}
因此,即使使用“if(stop)”检查,问题也会重现,我理解为什么。当我放置“Thread.MemoryBarrier()”之前,检查问题没有重现(至少我没有重现它),我理解为什么。但是我不明白的是,为什么当我改变条件并将“while(true)”而不是“while(!stop)”改为时,问题不再复制了?是否与“while(true)”声明的特殊处理有关?
当我改变条件并把“while(true)”而不是“while(!stop)”时,为什么问题不再复制?
行为取决于几个因素,如:硬件,操作系统,运行时环境......例如,在我的机器上,即使使用while (!stop)
的原始代码,也不会重现问题。我相信,问题可以通过while (true)
在另一个环境中重现。
Eric Lippert和Jon Skeet表示,除非我们是该领域的真正专家(Thread.MemoryBarrier
和link#1),否则我们不需要使用像link#2这样的低级技术。也许,您应该考虑使用volatile
关键字和stop
声明,它更明确地表达您的意图,并且让您不要使用Thread.MemoryBarrier
。甚至考虑使用Task
与CancellationToken
有能力取消Task
。
看你的用户名也许值得注意的是Eric Lippert和Jon Skeet关于.net
就像Gandalf关于魔法一样
更新
阅读Eric Lippert的评论如下。在你真正需要它之前,不要使用volatile
以及Thread.MemoryBarrier
。
while (true)
没有什么特别之处。
您的详细答案如下:https://msdn.microsoft.com/en-us/magazine/jj863136.aspx