The point is: it might work, but it isn't guaranteed to work by the spec. What people are usually after is code that works for the right reasons, rather than working by a fluke combination of the compiler, the runtime and the JIT, which might change between framework versions, the physical CPU, the platform, and things like x86 vs x64.
Understanding the memory model is a very very complex area, and I don't claim to be an expert; but people who are real experts in this area assure me that the behaviour you are seeing is not guaranteed.
You can post as many working examples as you like, but unfortunately that doesn't prove much other than "it usually works". It certainly doesn't prove that it is guaranteed to work. It would only take a single counter-example to disprove, but finding it is the problem...
No, I don't have one to hand.
Update with repeatable counter-example:
using System.Threading;
using System;
static class BackgroundTaskDemo
{
// make this volatile to fix it
private static bool stopping = false;
static void Main()
{
new Thread(DoWork).Start();
Thread.Sleep(5000);
stopping = true;
Console.WriteLine("Main exit");
Console.ReadLine();
}
static void DoWork()
{
int i = 0;
while (!stopping)
{
i++;
}
Console.WriteLine("DoWork exit " + i);
}
}
Output:
Main exit
but still running, at full CPU; note that stopping
has been set to true
by this point. The ReadLine
is so that the process doesn't terminate. The optimization seems to be dependent on the size of the code inside the loop (hence i++
). It only works in "release" mode obviously. Add volatile
and it all works fine.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…