假设我们有一个类
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的同一部分还给出了以下内容:
所以有
new Foo()
,first-action-in-first-thread)和这意味着还有:
new Foo()
,第一次断言中的第一个 Action )new Foo()
,第二个断言的第一个 Action )(由于“对于每个线程t,t中的同步 Action (第17.4.2节)的同步顺序与t的程序顺序(第17.4.3节)一致。”因此,我可以省略它们之间的步骤,例如
while(true)
循环)