假设我们有一个类
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();
}
因为happens-before是传递性的,所以不可能抛出AssertionError吗?
尽管 Foo 的 x 不是最终的,但由于 Thread.start() 的happens-before保证,从实例化 Foo 的线程中新创建的线程将看到调用 Thread.Start() 之前的所有更新.
但是,这个线程还产生了许多子线程,并且由于再次存在happens-before关系,我们是否可以说由于happens-before的传递属性,永远不会抛出AssertionError?
最佳答案
您的问题:
Since there is a happens-before relationship again, can we say that because of the transitive property of the happens-before, that AssertionError could never be thrown?
答案是肯定的。正如我们在 JLS8 section 17.4.5. Happens-before Order 中看到的那样:
- If hb(x, y) and hb(y, z), then hb(x, z).
JLS 的同一部分还给出了:
- A call to
start()
on a thread happens-before any actions in the started thread.
所以有
- hb(
new Foo()
,first-action-in-first-thread) 和 - hb(第一个线程中的第一个操作,第一个断言线程中的第一个操作)
- hb(第一个线程中的第一个操作,第二个断言线程中的第一个操作)
这意味着还有:
- hb(
new Foo()
,first-action-in-first-assertion-thread) - hb(
new Foo()
,第二个断言线程中的第一个操作)
(因为“对于每个线程 t,t 中的同步操作(第 17.4.2 节)的同步顺序与 t 的程序顺序(第 17.4.3 节)一致。”,我可以省略 -之间,如 while(true)
循环)
关于java - 调用 Thread.start() 时,happens-before 是否具有传递性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48255948/