发布模式下的无限循环

niv*_*lam 19 .net c# multithreading

当我在调试模式下运行以下代码时,它将成功完成并退出.但是,如果我在发布模式下运行以下代码,它将陷入无限循环而永远不会完成.

static void Main(string[] args)
{
    bool stop = false;

    new Thread(() =>
    {
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine("Set \"stop\" to true.");

    }).Start();

    Console.WriteLine("Entering loop.");

    while (!stop)
    {
    }

    Console.WriteLine("Done.");
}
Run Code Online (Sandbox Code Playgroud)

哪种优化导致它陷入无限循环?

Chr*_*ain 18

我的猜测是stop主线程上变量的处理器缓存.在调试模式下,内存模型更严格,因为调试器需要能够在所有线程中提供变量状态的合理视图.

尝试创建一个字段并将其标记为volatile:

volatile bool stop = false;

static void Main(string[] args)
{

    new Thread(() =>
    {
        Thread.Sleep(1000);
        stop = true;
        Console.WriteLine("Set \"stop\" to true.");

    }).Start();

    Console.WriteLine("Entering loop.");

    while (!stop)
    {
    }

    Console.WriteLine("Done.");
}
Run Code Online (Sandbox Code Playgroud)

  • @UweKeim:获取/设置一个bool绝对是原子的.这是在规范中.http://stackoverflow.com/questions/9666/is-accessing-a-variable-in-c-sharp-an-atomic-operation (2认同)

ABH*_*ABH 11

因为它不是线程安全的,所以更新stop子线程内的主线程变量.它永远是不可预测的.要处理这种情况,请查看本文.

volatile关键字指示编译器在每次从该字段读取时生成一个获取栅栏,并在每次写入该字段时生成一个释放栅栏.获取栅栏可防止其他读/写在栅栏前移动; 释放栅栏可防止在栅栏后移动其他读/写.这些"半栅栏"比完全栅栏更快,因为它们为运行时和硬件提供了更多的优化空间.