Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 调用start生成的线程是否可以看到thread.start之前发生的一切?_Java_Multithreading_Concurrency_Visibility_Happens Before - Fatal编程技术网

Java 调用start生成的线程是否可以看到thread.start之前发生的一切?

Java 调用start生成的线程是否可以看到thread.start之前发生的一切?,java,multithreading,concurrency,visibility,happens-before,Java,Multithreading,Concurrency,Visibility,Happens Before,现在在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() 现在这个方法正在运行,在调用t

现在在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赋值为8,都不会有任何区别。所以这是可以重新排序的,但由于担保之前发生的情况,这是不可能的吗

java规范并没有明确指出这一点。而是说

当一条语句调用Thread.start()时,与该语句具有before关系的每一条语句

然而,k=8并不表示a发生在与该语句的关系之前

我甚至不知道它们的意思是什么,除非你使用同一个监视器锁定,否则与start方法有一个before关系

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),那么T1在启动T2之前所做的任何更改都保证对T2可见。作为一名程序员,这才是最重要的。只要不违反此保证,编译器就可以执行重新排序。你当然可以参考JLS,但我认为你已经参考了

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

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

另外,如果我们用另一种方式来讨论它,那么可以安全地说thread.start()永远不能被重新排序

关键是-新启动的线程保证将k的值视为8。如果新启动的线程不读取k(或父线程设置的任何其他变量),则允许编译器对此类操作重新排序,但这对程序员来说并不重要(程序员无论如何都会得到保证)

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

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


总而言之,如果一个线程(T1)启动另一个线程(T2),那么T1在启动T2之前所做的任何更改都保证对T2可见。作为一名程序员,这才是最重要的。只要不违反此保证,编译器就可以执行重新排序。您当然可以参考JLS,但我想您已经参考过了。

您看到此线程了吗?是的,但是我想我需要更多的证实,因为我很难理解别人的想法。永远不要感谢链接你看到这条线了吗?是的,但是我想我需要更多的证实,因为我很难理解别人的想法。永远不要错过这个环节。这就是我要找的。那么这个怎么样?在创建新线程的线程中,让我们假设int x=someGlobalVariable。然后在新线程中,它使用x。x是否保证是someGlobalVariable的最新值,就好像someGlobalVariable是挥发性的一样?否。before是可传递的。因此,如果(且仅当)设置someGlobalVariable的操作与int x=someGlobalVariable有一个before-before关系,那么您就有了这个保证。否则,如果someGlobalVariable是由其他一些随机线程设置的,那么您就不会得到这个保证。太棒了。我喜欢你回答问题的方式。它是明确的,而且容易理解。这就是我要找的。那么这个怎么样?在创建新线程的线程中,让我们假设int x=someGlobalVariable。然后在新线程中,它使用x。x是否保证是someGlobalVariable的最新值,就好像someGlobalVariable是挥发性的一样?否。before是可传递的。因此,如果(且仅当)设置someGlobalVariable的操作与int x=someGlobalVariable有一个before-before关系,那么您就有了这个保证。Ot