多线程 - 了解内存障碍和易失性

问题描述 投票:0回答:2

我正在研究着名的'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)”声明的特殊处理有关?

c# multithreading thread-safety clr memory-barriers
2个回答
1
投票

当我改变条件并把“while(true)”而不是“while(!stop)”时,为什么问题不再复制?

行为取决于几个因素,如:硬件,操作系统,运行时环境......例如,在我的机器上,即使使用while (!stop)的原始代码,也不会重现问题。我相信,问题可以通过while (true)在另一个环境中重现。

Eric Lippert和Jon Skeet表示,除非我们是该领域的真正专家(Thread.MemoryBarrierlink#1),否则我们不需要使用像link#2这样的低级技术。也许,您应该考虑使用volatile关键字和stop声明,它更明确地表达您的意图,并且让您不要使用Thread.MemoryBarrier。甚至考虑使用TaskCancellationToken有能力取消Task

看你的用户名也许值得注意的是Eric Lippert和Jon Skeet关于.net就像Gandalf关于魔法一样

更新

阅读Eric Lippert的评论如下。在你真正需要它之前,不要使用volatile以及Thread.MemoryBarrier


-1
投票

while (true)没有什么特别之处。

您的详细答案如下:https://msdn.microsoft.com/en-us/magazine/jj863136.aspx

© www.soinside.com 2019 - 2024. All rights reserved.