发布模式下的无限循环

时间:2012-05-25 04:16:36

标签: c# .net multithreading

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

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.");
}

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

4 个答案:

答案 0 :(得分: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.");
}

答案 1 :(得分:11)

因为它不是线程安全的,所以更新子线程内的主线程变量stop。它永远是不可预测的。要处理此类情况,请查看this article

  

volatile关键字指示编译器生成   在每次从该字段读取时获取栅栏,并释放栅栏   每次写入该字段。获取围栏阻止其他   在围栏前移动读/写;释放围栏   防止在围栅后移动其他读/写。这些   “半围栏”比完全围栏更快,因为它们给了   运行时和硬件的优化范围更广。

答案 2 :(得分:0)

线程不安全代码是不可预测的。主要问题是从另一个线程更改一个线程变量。使变量全局或不稳定。您可以按照

进行操作
static 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.");
}

答案 3 :(得分:0)

看起来对局部变量的值进行某种优化 - 更改为字段使其终止正常(请注意,在实际代码中应使用易失性或正确的锁定):

using System;
using System.Threading;

class Program
{
    static 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.");
    }
}