C# 释放模式下的无限循环

C# 释放模式下的无限循环,c#,.net,multithreading,C#,.net,Multithreading,当我在调试模式下运行以下代码时,它将成功完成并退出。但是,如果我在发布模式下运行下面的代码,它将陷入无限循环中,永远无法完成 static void Main(string[] args) { bool stop = false; new Thread(() => { Thread.Sleep(1000); stop = true; Console.WriteLine("Set \"stop\" to true.")

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

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

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

因为它不是线程安全的,所以更新子线程内的主线程变量
stop
。它总是不可预测的。要处理任何类似的情况,请查看

volatile关键字指示编译器生成 在该区域的每次读取上获取围栏,并在 每个人都要写信给那个领域。一道篱笆挡住了另一道墙 在围栏之前进行读/写操作;围栏 防止在围栏后移动其他读/写操作。这些 “半篱笆”比全篱笆快,因为它们提供 运行时和硬件有更多的优化空间


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

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


线程不安全代码是不可预测的。主要问题是从另一个线程更改一个线程变量。使变量成为全局变量或可变变量。你可以按照下面的方法来做

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

看起来像是局部变量值的某种优化-更改为字段使其终止ok(注意,实际代码中应使用volatile或correct锁定):


是否不需要在线程之间同步访问
stop
。编译将构建一个真正的stop安装。请看一下新的CancellationToken类。发明它们是为了解决这个问题。Volatile对正确性有好处,但为了避免优化,将其设置为字段而不是局部变量就足够了。@AlexeiLevenkov我可能弄错了,但我相信这是CLR的一个实现细节,理论上(虽然可能不实际)可能会更改。我想知道为什么不同步对变量的访问。我总是这样做,因为我假设获取/设置
bool
变量不是一个原子操作。我错了吗?我想很难找到一个合理的非原子方法来设置或获取布尔变量。。。缓存(由CPU或编译器本身)是造成这种情况的原因。@UweKeim:bool的get/set肯定是原子的。它在规格里。
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.");
}
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.");
    }
}