执行java语句的顺序

时间:2016-07-06 13:35:52

标签: java jvm

由于无法保证执行顺序。在下面的程序中,main方法的执行顺序如下所示?

 t2.start();
 t2.join(); 
 t1.start();
 t1.join(); 

计划是:

public class Puzzle {
  static boolean answerReady = false;
  static int answer = 0;
  static Thread t1 =
      new Thread() {
        public void run() {
          answer = 42;
          answerReady = true;
        }
      };
  static Thread t2 =
      new Thread() {
        public void run() {
          while (!answerReady) Thread.sleep(100);
          System.out.println("The meaning of life is: " + answer);
        }
      };

  public static void main(String[] args) throws InterruptedException {
    t1.start();
    t2.start();
    t1.join();
    t2.join();
  }
}

编辑:在看到评论之后想要添加一些东西

  1. answerReady可能永远不会成真。同意。
  2. 可以更改执行顺序时的特殊条件是什么?
  3. 为什么main方法在这里正确同步?

2 个答案:

答案 0 :(得分:3)

Java语言规范规定了符合JVM的功能与否。参见

  

§17.4.5. Happens-before Order

     

发生在之前的关系可以订购两个动作。如果一个动作发生在另一个动作之前,那么第一个动作在第二个动作之前是可见的并且在第二个动作之前被命令。

     

如果我们有两个动作 x y ,我们会写 hb(x,y)来表示 x发生 - 在y 之前。

     
      
  • 如果 x y 是同一个帖子的操作, x 按照程序顺序出现在 y 之前,然后 hb(x,y)
  •   
  • ...
  •   

由于您对start()join()的调用是同一线程的操作,因此会根据程序顺序对它们进行排序。

我认为,显而易见的是,如果不存在这种简单的保证,即使单线程编程也是不可能的。

这并不意味着代码中没有重新排序。它只暗示这种优化必须以在执行此代码时保留这些操作的可观察行为的方式发生。

这里的要点是,虽然主线程将始终执行您告诉它要执行的操作,但其他线程没有发生在之前与这些操作之间的关系,可能看不到操作以同样的方式。在您的情况下,显示三个线程,有几种关系:

继续§17.4.5

  
      
  • ...
  •   
  • 如果 hb(x,y) hb(y,z),则 hb(x,z)
  •   
     

...

     
      
  • 线程上的start()调用发生在已启动线程中的任何操作之前。
  •   
  • 线程中的所有操作都发生在任何其他线程成功从该线程上的join()返回之前。
  •   

由此可以推导出代码的所有三个线程都同意主线程在大多数部分中所做的事情。

当然,这并没有改变两个衍生线程不正确(根本没有)同步的事实,t2可能会打印值0而不是42或从不终止。

答案 1 :(得分:2)

没有。主线程上的执行顺序是您在main中声明的那样:

t1.start();
t2.start();
t1.join();
t2.join();

唯一没有保护的是线程t1t2的内容。