在thread.start之前发生的所有事情都可以生成调用start的线程吗?

现在已经有很好的答案已经在stackoverflow上,但他们没有给我我想要的明确答案。

假设你有一个方法

Dosomething(); doAnother(); int x = 5; Runnable r = new Runnable(){ public void run(){ int y = x; x = 7; System.out.println(z);} } new Thread(r).start() 

现在同时这个方法正在运行,在调用thread.start之前,一些全局非易失性变量z从4变为5。

由于z发生在thread.start之前,程序是否会保证打印5?

另外,如果我们以这种方式讨论它,那么可以肯定地说thread.start()永远不会被重新排序。

根据被调用的那个线程的意义开始,就好像到那一点的一切都是顺序的。 比如说我们有

 int k = 8; new Thread(() -> {}).start() 

现在……在该线程的视角中,无论是首先调用start还是分配k,都不会产生影响。所以这可以重新排序,但是因为在保证之前发生了,这是不可能的?

java规范没有说明这一点的强烈声明。 相反它说

当一个语句调用Thread.start()时,每个语句都与该语句有一个before-before关系

然而,k = 8并不是在与该陈述的关系之前发生的……

我甚至不确定他们的意思是在与start方法的关系之前发生了什么事情,除非您使用相同的监视器锁定

 synchronized(this){ int k = 8;} synchronized(this) { new Thread(() -> {}).start();} 

对于一个更可怕的情况我们有这个代码

 Socket con = socket.accept(); Runnable r = new Runnable(){ public void run(){ handleRequest(con)} } new Thread(r).start(); 

然后新线程碰巧发现con为null?

有人可以就这些话题给我一个明确的答案吗?

由于z发生在thread.start之前,程序是否会保证打印5?

如果z的值由调用start()方法的线程设置,则为yes。 否则,没有。 新启动的线程可以保证看到启动它的线程所做的更改,而不是其他线程所做的更改。

另外,如果我们以这种方式讨论它,那么可以肯定地说thread.start()永远不会被重新排序。

重点是 – 新启动的线程保证看到k的值为8.如果新启动的线程不读取k(或由父线程设置的任何其他变量),则允许编译器重新排序操作,但对程序员来说无关紧要(程序员无论如何都得到保证)

然后新线程碰巧发现con为null?

假设新线程具有对con的引用,则保证在新线程启动之前初始化con(因为JMM保证在调用start()之前父线程所做的任何更改对于新线程是可见的)

总而言之 – 是一个线程(T1)启动另一个线程(T2),然后在开始T2之前由T1做出的任何更改都保证对T2可见。 作为程序员,这才是最重要的。 只要不破坏此保证,编译器就可以执行重新排序。 您当然可以参考JLS,但我认为您已经拥有。