假设我们有一个类

class Foo {
    int x;
    Foo() {
        x = 5;
    }
}

和一些客户代码
public static void main(String[] args) {
    Foo foo = new Foo();
    new Thread(() -> {
        while (true) {
            new Thread(() -> {
                if (foo.x != 5) {
                    throw new AssertionError("this statement is false 1");
                }
                new Thread(() -> {
                    if (foo.x != 5) {
                        throw new AssertionError("this statement is false 2");
                    }
                }).start();
            }).start();
        }
    }).start();
}

是否因为发生事前传递而引发AssertionError,这是不可能的吗?

即使Foo的x不是最终的,由于Thread.start()的事前保证,从实例化Foo的线程中新创建的线程将看到直到调用Thread.Start()为止的所有更新。

但是,此线程还产生许多子线程,并且由于再次存在事前发生关系,我们可以说由于事前发生的传递属性,所以永远不会抛出AssertionError吗?

最佳答案

你的问题:



答案是肯定的。正如我们在JLS8 section 17.4.5. Happens-before Order中看到的:



JLS的同一部分还给出了以下内容:



所以有

  • hb(new Foo(),first-action-in-first-thread)和
  • hb(第一个操作在第一个线程中,第一个操作在第一个断言线程中)
  • hb(第一个 Action 在第一个线程中,第一个 Action 在第二个断言线程中)

  • 这意味着还有:
  • hb(new Foo(),第一次断言中的第一个 Action )
  • hb(new Foo(),第二个断言的第一个 Action )

  • (由于“对于每个线程t,t中的同步 Action (第17.4.2节)的同步顺序与t的程序顺序(第17.4.3节)一致。”因此,我可以省略它们之间的步骤,例如while(true)循环)

    10-07 19:01
    查看更多