使此可见性示例失败

Era*_*dan 9 java concurrency

Java Concurrency in Practice中我认为令人惊讶的一个例子(至少我)是这样的:

public class Foo {

  private int n;

  public Foo(int n) {
    this.n = n;
  }

  public void check() {
    if (n != n) throw new AssertionError("huh?");

  }
}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是(至少对我来说)声称这不是线程安全的,不仅它不安全,而且检查方法也有可能抛出断言错误.

解释是,如果没有同步/标记n为volatile,则不同线程之间没有可见性保证,并且n的值可以在线程读取时更改.

但我想知道它在实践中发生的可能性有多大.或者更好,如果我能以某种方式复制它.

所以我试图编写会触发断言错误的代码,没有运气.

有没有直接的方法来编写一个测试,证明这个可见性问题不仅仅是理论上的?

或者它是否在最近的JVM中发生了变化?

编辑:相关问题:非线程安全对象发布

Pet*_*rey 6

但我想知道它在实践中发生的可能性有多大.

非常不可能的esp,因为JIT可以n变成一个局部变量而只读一个.

极不可能的线程安全漏洞的问题在于,有一天,您可能会更改一些无关紧要的内容,例如您选择的处理器或JVM,并且突然您的代码会随机中断.

或者更好,如果我能以某种方式复制它.

不保证您也可以重现它.

有没有直接的方法来编写一个测试,证明这个可见性问题不仅仅是理论上的?

在某些情况下,是的.但是这个是难以证明的,部分原因是因为JVM没有被阻止比JLS说的最小的线程更安全.

例如,HotSpot JVM通常会执行您期望的操作,而不仅仅是文档中的最小值.例如,根据javadoc,System.gc()只是一个提示,但默认情况下,HotSpot JVM每次都会这样做.