我正在研究著名的“坚果中的C#”之后的c#线程,并且在研究Thread.MemoryBarrier()现象时,偶然发现Why we need Thread.MemoryBarrier()?上Brian的示例时,我被吓死了。
我拥有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();
}
}
因此,即使使用“如果(停止)”检查,问题也会重现,并且我理解原因。当我将“ Thread.MemoryBarrier()”放置在该检查问题之前时,该问题不会重现(至少我无法重现),并且我理解为什么。但是我不明白的是,当我改变while条件并放置“ while(true)”而不是“ while(!stop)”时,为什么问题不再重现了?它与“ while(true)”语句的特殊处理有关吗?
答案 0 :(得分:1)
当我更改while条件并放入“ while(true)”而不是“ while(!stop)”时,为什么问题不再重现了?
该行为取决于多个因素,例如:硬件,操作系统,运行时环境...例如,在我的机器上,即使使用while (!stop)
编写原始代码也无法重现该问题。而且我相信,可以在其他环境上使用while (true)
重现该问题。
埃里克·利珀特(Eric Lippert)和乔恩·斯基特(Jon Skeet)指出,除非我们是该领域的真正专家(link#1和link#2),否则我们不需要使用诸如Thread.MemoryBarrier
之类的低级技术。可能您应该考虑在volatile
声明中使用stop
关键字,这样可以更明确地表达您的意图,并避免使用Thread.MemoryBarrier
。甚至考虑将Task
与CancellationToken
一起使用,以具有取消Task
的能力。
关于您的用户名,也许值得一提的是,关于.net
的Eric Lippert和Jon Skeet就像是关于魔术的Gandalf
更新
在下面阅读Eric Lippert的评论。在您真正需要它们之前,不要同时使用volatile
和Thread.MemoryBarrier
。
答案 1 :(得分:-1)
while (true)
没什么特别的。
您的详细答案描述如下: https://msdn.microsoft.com/en-us/magazine/jj863136.aspx