0

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?

2 Answers2

1

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.

AlbertK
  • 11,841
  • 5
  • 40
  • 36
  • 1
    Thanks for the shout-out; a couple fun facts for you. First, *I am not knowledgable enough to know when to use volatile vs memory barrier and so on*. I'm not an expert in this area; what I am an expert on is *knowing that it is too complicated for me to get it right*. That's why I tell people to just take out a lock. If your application needs performance such that an uncontended lock is too expensive, you should hire an expert on nano-scale optimizations. Second, my alias on Commodore 64 BBS's was "Radagast". :-) – Eric Lippert Feb 20 '19 at 23:20
  • Thanks, especially for the second fact. I was almost accurate about this:) I've read your [article about volatility](https://blogs.msdn.microsoft.com/ericlippert/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three/) and it is clear that `volatile` is not so obvious for us (non experts in this area). So do you recommend not to use `volatile` as I suggested in the answer even in this basic case? – AlbertK Feb 21 '19 at 10:51
  • 1
    My recommendation is: if you use `volatile` it is because you are doing something super dangerous: modifying memory on two threads without a lock. You've got a kitchen full of cooks and you're trying to juggle their knives while they're using them; the slightest mistake and someone is going to get cut. You had better know exactly why `volatile` is correct and what the implications are on correctness and performance. But I suspect many people use volatile because someone on the internet told them that if they do, their threading performance problems will vanish at no cost. – Eric Lippert Feb 21 '19 at 13:41
  • 1
    Hi, Albert. Thank you for your response. And I also thank Eric for honest and practical advice. – Frodo Baggins Feb 23 '19 at 11:16
-1

There is nothing special about while (true).

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

Nick
  • 4,787
  • 2
  • 18
  • 24
  • In the current state this is a **link-only answer**, which we want to avoid on Stack Overflow. Please, add some details from the referenced page into the answer post. – Tsyvarev Feb 19 '19 at 23:12
  • Nick, thank you. Any good link where I can learn new stuff is acceptable to me. – Frodo Baggins Feb 23 '19 at 11:17