简体   繁体   中英

Multithreading - Understanding memory barriers and volatile

I'm studying c# threading following famous 'C# in a Nutshell' and during investigation of Thread.MemoryBarrier() phenomena, I was scared to death when I stumbled upon Brian's example on Why we need Thread.MemoryBarrier()? .

I'm having i-7 8700K processor and 4.6.1 .NET and I managed to reproduce the problem (program never ends) even with following changes in program:

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();
    }
}

So, even with "if (stop)" check, problem reproduces and I understand why. When I place "Thread.MemoryBarrier()" before that check problem doesn't reproduce (at least I failed to reproduce it) and I understand why. But what I don't understand is why problem is not reproducing anymore when I change while condition and put "while (true)" instead of "while (!stop)"? Does it have something to do with special treatment of "while (true)" statement?

why problem is not reproducing anymore when I change while condition and put "while (true)" instead of "while (!stop)"?

The behavior depends on several factors like: hardware, operating system, runtime environment... For example, on my machine the problem is not reproduced even with your original code with while (!stop) . And I believe, the problem can be reproduced with while (true) on another environment.

Eric Lippert and Jon Skeet state that we don't need to use such low-level techniques like Thread.MemoryBarrier unless we are real experts in that area ( link#1 and link#2 ). Probably, you should consider to use volatile keyword with stop declaration which expresses your intention more explicitly and lets you not to use Thread.MemoryBarrier . Or even consider use of Task with CancellationToken to have ability to cancel Task .

Looking to your username maybe it worth to note that Eric Lippert and Jon Skeet regarding .net are like Gandalf regarding magic

Update

Read Eric Lippert's comments below. Don't use volatile as well as Thread.MemoryBarrier until you really need it.

There is nothing special about while (true) .

Your detailed answer is described here: https://msdn.microsoft.com/en-us/magazine/jj863136.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM