发布模式下的无限循环

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

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 :

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

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

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

线程不安全代码是不可预测的。 主要问题是从另一个线程更改一个线程变量。 使变量全局或不稳定。 您可以通过以下方式完成

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

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

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