Java线程-内存一致性错误

Java线程-内存一致性错误,java,multithreading,shared-memory,Java,Multithreading,Shared Memory,我在看一本书 但我不能确切地理解内存一致性错误是什么?我在谷歌上搜索了一下,但没有找到任何有用的教程或文章 我知道这个问题是主观的,所以你可以给我提供关于上述主题的文章的链接 如果你能用一个简单的例子来解释,那就太好了。你可以通过阅读了解更多关于这个主题的信息。这些危害涉及流水线处理,但实际上与多线程发生的问题相同。这基本上意味着两个不同的线程正在更新内存中的同一位置,如果您以某种顺序依赖这些更新,那么您可能会惊讶地发现,您无法保证更新发生的顺序 例如,如果您有两条语句: x = y + z

我在看一本书

但我不能确切地理解内存一致性错误是什么?我在谷歌上搜索了一下,但没有找到任何有用的教程或文章

我知道这个问题是主观的,所以你可以给我提供关于上述主题的文章的链接

如果你能用一个简单的例子来解释,那就太好了。

你可以通过阅读了解更多关于这个主题的信息。这些危害涉及流水线处理,但实际上与多线程发生的问题相同。这基本上意味着两个不同的线程正在更新内存中的同一位置,如果您以某种顺序依赖这些更新,那么您可能会惊讶地发现,您无法保证更新发生的顺序

例如,如果您有两条语句:

  x = y + z;
  r = x + z;

在单个线程中,则没有问题,因为r的值始终是一致的。但是,在多线程中,有可能或其中一个语句首先出现,并且r的值更难预测。

Hm。他们基本上是在讨论“可见性问题”和“重新排序问题”(至少在Java IMO中,这个术语更为常见)。我认为这个链接:解释了教程所讨论的内容,使用了更常见的术语(也许sun试图使用“更简单”的词汇或其他东西)

基本上,在没有任何同步的情况下,线程可以看到一个简单字段的不同值。考虑这个例子:

class Foo
{
  int bar = 0;

  void unsafeCall ( )
  {
    final Foo thisObj = this;

    Runnable r = new Runnable ( )
    {
      public void run ( )
      {
        thisObj.bar = 1;
      }
    }

     Thread t = new Thread(r);

     t.start( );
     Thread.sleep( 1000 );

     // May print bar = 0
     System.out.println( "bar = " + bar );
  }
}
避免内存一致性错误的最简单方法是将
bar
字段声明为
volatile
(有关更多详细信息,请参阅此处:)


这种迫使线程重新检查内存的行为称为内存屏障。内存障碍的另一个例子是
同步的
方法/块。

如果您想更深入地了解共享内存一致性模型,我建议您参考以下教程


在搜索这个问题时,我发现了一个很好的例子。如下所示:

Accesses to main memory might not occur in the same order that the CPU initiated them, particularly for writes (which often go through hardware write buffers so the CPU needn't wait for them). If CPU 1 writes the Answer to location A and then writes the AnswerIsReady flag to B, CPU 2 may see the change to B before it sees the change to A, and thus get the WrongAnswer. Making either or both writes atomic doesn't help; what's needed is something called a "memory barrier." 对主内存的访问可能不会同时发生 命令CPU启动它们,特别是写操作 (通常通过硬件写入缓冲区,因此CPU 不必等待他们)。如果CPU 1将答案写入 位置A,然后将应答准备标志写入B, CPU 2可能在看到更改之前看到B的更改 到A,从而得到错误的答案。做一个或两个 写原子没有帮助;我们需要的是一些东西 被称为“记忆屏障” 通过