5

为什么在这部分代码complete被缓存?

static void Main()
{
  bool complete = false; 
  var t = new Thread (() =>
  {
    bool toggle = false;
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();        // Blocks indefinitely
}

但在这部分不是吗?

static void Main()
{
  bool complete = false;
  bool toggle = false; 
  var t = new Thread (() =>
  {
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();  
}
4

3 回答 3

3

您正在跨线程进行不同步的数据共享。警报器现在应该响起。

据我了解内存模型允许 JIT 读取complete一次并将其存储在寄存器中。因此,来自 Main 的更新永远不会变得可见。

至于解决这个问题,最简单的方法是在对complete. 您也可以使用Thread.VolatileReadThread.VolatileWrite

于 2013-02-28T23:45:06.877 回答
3

不要确定缓存是否会在上述所有架构上发生,或者甚至在程序的多次运行中总是会像上面那样发生。

可能是因为在第二种情况下,lambda 正在修改闭包,而在第一种情况下,它只访问闭包。当然,这只是一个疯狂的猜测。

更重要的是,无法保证何时完成缓存内存边界仅指定线程何时使用缓存值

最重要的是,您不能依赖缓存的发生。

于 2013-02-28T23:50:48.510 回答
0

在我的情况下,这两个示例都完成了,但是您的 lambda/delegate 可以在不同的编译器中进行不同的编译,这可能是问题所在。

您的委托正在访问一个修改后的闭包,这可能会导致一堆问题,而您显然已经找到了一个。看看 Jon Skeet 在此处提供的答案Access to Modified Closure,这不是完全相同的问题,但此处描述的原因也适用于您的情况。

于 2013-02-28T22:59:18.963 回答