调用 Thread.start() 时 happens-before 是否具有传递性?
Is happens-before transitive when calling Thread.start()?
假设我们有一个 class
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() 的先行保证,从实例化 Foo 的线程创建的新线程将看到所有更新,直到调用 Thread.Start().
然而,这个线程也产生了许多子线程,并且由于再次发生了之前发生的关系,我们可以说因为发生之前的传递属性,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) and
- hb(第一个线程中的第一个动作,第一个断言线程中的第一个动作)
- hb(第一个线程中的第一个动作,第二个断言线程中的第一个动作)
这意味着还有:
- hb(
new Foo()
, 第一个断言线程中的第一个动作)
- hb(
new Foo()
, 第二个断言线程中的第一个动作)
(因为 "For each thread t, the synchronization order of the synchronization actions (§17.4.2) in t is consistent with the program order (§17.4.3) of t.",我可以省略中间的步骤,比如 while(true)
循环)
假设我们有一个 class
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() 的先行保证,从实例化 Foo 的线程创建的新线程将看到所有更新,直到调用 Thread.Start().
然而,这个线程也产生了许多子线程,并且由于再次发生了之前发生的关系,我们可以说因为发生之前的传递属性,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) and - hb(第一个线程中的第一个动作,第一个断言线程中的第一个动作)
- hb(第一个线程中的第一个动作,第二个断言线程中的第一个动作)
这意味着还有:
- hb(
new Foo()
, 第一个断言线程中的第一个动作) - hb(
new Foo()
, 第二个断言线程中的第一个动作)
(因为 "For each thread t, the synchronization order of the synchronization actions (§17.4.2) in t is consistent with the program order (§17.4.3) of t.",我可以省略中间的步骤,比如 while(true)
循环)