代码之家  ›  专栏  ›  技术社区  ›  ricky

为什么强内存模型不阻止CPU缓存?

  •  1
  • ricky  · 技术社区  · 6 年前

    约瑟夫阿尔巴哈里在他的博客中说 here 即使在高内存顺序的CPU(如普通的英特尔酷睿2和奔腾处理器)上,

    以下程序从不终止,因为完整变量缓存在 CPU寄存器。在中插入对thread.memorybarrier的调用 当循环(或锁定读取完成)修复错误时。

    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
    }
    

    按照 here 不应该这样?

    一个强大的硬件内存模型是每一条机器指令都隐含着获取和释放语义。因此,当一个CPU核心执行一系列写入时,其他每个CPU核心都会看到这些值的更改顺序与写入顺序相同。

    我对这两个引语感到困惑,有人能给我一个更详细的解释吗?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Siddhesh Rane    6 年前

    一个强大的硬件内存模型是每一条机器指令都隐含着获取和释放语义。因此,当一个CPU核心执行一系列写入时,其他每个CPU核心都会看到这些值的更改顺序与写入顺序相同。

    在本例中,内存写入顺序并不重要。随着线程不断地进行轮询,它最终将获取 complete 变量。

    但是,这与内存和缓存有关,这些内存和缓存必须向所有处理器呈现相同的视图。寄存器是每个CPU的私有寄存器,不必与其他CPU共享它们的内容。

    这个 完成 变量在线程t的寄存器中。没有任何其他处理器可以更新这个寄存器,因为它实际上没有链接到内存系统。使变量 volatile 将解决此问题,因为它将保存在内存中而不进行注册。

    以下程序从不终止,因为完整变量缓存在CPU寄存器中。在while循环中插入对thread.memorybarrier的调用(或锁定读取完成)可以修复错误。

    这两个修复程序基本上都将变量保存在内存中,以便它工作。