Java线程 - 内存一致性错误

15

我正在阅读一篇关于并发的Sun教程

但是我不太明白什么是内存一致性错误?我在谷歌上搜索了一下,但没有找到任何有用的教程或文章。

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

如果您能用一个简单的例子来解释一下就更好了。

5个回答

7
你可以阅读读后写(RAW)、写后写(WAW)和写后读(WAR)危险性来了解更多相关主题。这些危险性是指流水线进程,但实际上,在多线程中也会出现同样的问题。这基本上意味着两个不同的线程正在更新内存中的同一位置,如果你依赖于这些更新以特定顺序进行,则可能会惊讶地发现无法保证更新的顺序。
例如,如果你有两个语句:
  x = y + z;
  r = x + z;

如果在单个线程中,那么你没有问题,因为 r 的值始终保持一致。但是在多个线程中,有可能其中一个语句先执行,而 r 的值更难以预测。


4

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

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 (有关详细信息,请参见此处:https://www.ibm.com/developerworks/java/library/j-jtp06197/)。
强制线程重新检查内存的行为称为 内存屏障。另一个 内存屏障 的例子是 synchronized 方法/块。

3

1

我在搜索这个问题时找到了一个很好的例子。如下:

    访问主内存可能不会按照CPU发起它们的顺序进行,特别是对于写操作(通常通过硬件写缓冲区进行,因此CPU无需等待它们)。如果CPU 1将答案写入位置A,然后将AnswerIsReady标志写入B,则CPU 2可能在看到对A的更改之前就看到对B的更改,从而得到错误的答案。使任一或两个写操作原子化都没有帮助;需要的是所谓的“内存屏障”。

通过http://www.velocityreviews.com/forums/t390825-memory-consistency-errors.html获取


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接