java - java语句的执行顺序

标签 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 方法在这里正确同步?

最佳答案

Java 语言规范规定了符合标准的 JVM 可以做什么或不可以做什么。参见

§17.4.5. Happens-before Order

Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.

If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

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

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

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

这里的要点是,虽然主线程将始终执行您告诉它执行的操作,但与这些操作中的任何一个没有发生之前关系的其他线程可能看不到这些操作以同样的方式。在您的例子中,显示了三个线程,存在多种关系:

§17.4.5 的延续

  • If hb(x, y) and hb(y, z), then hb(x, z).

  • A call to start() on a thread happens-before any actions in the started thread.
  • All actions in a thread happen-before any other thread successfully returns from a join() on that thread.

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

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

关于java - java语句的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38225392/

相关文章:

java - 需要身份验证。 http ://localhost:8080 requires a username and password in Tomcat

java - 仅过滤具有特定参数名称的 post 方法请求

java - Java GC 日志行之间有什么区别? ("Total time for which..."与 "[GC")

Java进程在发送kill信号时不会终止

oop - Clojure 的核心是面向对象的吗? (序列中的多态性)

java - 为什么 HashSet 对 getExactSizeIfKnown 返回 -1

java - 在字符串中搜索模式

java - 使用 Apache POI 将宏复制到模板文件中?

java - 如何调查 JVM 崩溃的原因?

java - NMT 类提交与 Jstat 压缩类空间