Java 调用Thread.start()时,是否在可传递之前发生?

Java 调用Thread.start()时,是否在可传递之前发生?,java,multithreading,concurrency,visibility,safe-publication,Java,Multithreading,Concurrency,Visibility,Safe Publication,假设我们有一节课 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

假设我们有一节课

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();
}
是否因为之前发生的事件是可传递的,所以不可能抛出断言错误

尽管Foo的x不是最终的,但由于Thread.start()的before保证,从实例化Foo的线程新创建的线程将看到调用Thread.start()之前的所有更新

但是,此线程也会产生许多子线程,并且由于再次存在“发生在之前”关系,我们是否可以说,由于“发生在之前”的可传递属性,该断言错误永远不会被抛出?

您的问题:

既然又有一段“先发生后发生”的关系,我们能这么说吗 由于之前发生的事件具有传递性,所以 断言错误永远不会被抛出

答案是肯定的。正如我们在下面的例子中所看到的:

  • 如果hb(x,y)和hb(y,z),那么hb(x,z)
JLS的同一章节中也给出了:

  • 对线程的
    start()
    调用发生在已启动线程中的任何操作之前
确实如此

  • hb(
    new Foo()
    ,第一个线程中的第一个操作)和
  • hb(第一个线程中的第一个操作,第一个断言线程中的第一个操作)
  • hb(第一个线程中的第一个操作,第二个断言线程中的第一个操作)
这意味着还有:

  • hb(
    newfoo()
    ,第一个断言线程中的第一个操作)
  • hb(
    newfoo()
    ,第二个断言线程中的第一个操作)

(由于“对于每个线程t,t中同步操作(§17.4.2)的同步顺序与t的程序顺序(§17.4.3)一致”,我可以省略中间的步骤,如
while(true)
循环)

beautiful!这
如果hb(x,y)和hb(y,z),那么hb(x,z)
实际上解释了这一点。1+顺便说一句,当您引用JLS时,再次阅读答案“(因为“对于每个线程……可以省略中间的步骤,如while(true)循环)”,我认为,当您有一些同步操作,例如thread.start(),那么这些事情就不能重新排序,所以逻辑上应该首先出现的所有事情单个线程中的(无论是上面的行还是从右向左计算的行)都将运行,例如Foo x=new Foo();new thread(()->{}).start();new thread(()->{}).start();Foo总是在下两个线程以及Runnable之前首先计算lambda@katiex7-允许编译器对任一线程中的指令重新排序,但这不会影响该线程的独立执行。JLS 17.4.内存模型执行构造调用
x=5;
hb
Foo-Foo=new-Foo()
。?