java 个语句的执行顺序
Order of execution java statements
因为无法保证执行顺序。在下面的程序中,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();
}
}
编辑:看到评论想补充几点
- answerReady 可能永远不会变为真。同意。
- 可以更改执行顺序的特殊情况是什么?
- 为什么 main 方法在这里正确同步?
没有。主线程上的执行顺序与您在 main
:
中声明的一样
t1.start();
t2.start();
t1.join();
t2.join();
唯一没有保证的是线程 t1
和 t2
.
的内容
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()
的调用是同一线程的操作,因此它们按照程序顺序进行排序。
我认为,如果不存在这种简单的保证,那么很明显,即使是单线程编程也是不可能的。
这并不意味着代码中没有重新排序。它仅意味着此类优化必须以在执行此代码时保留这些操作的可观察行为的方式发生。
这里的重点是,虽然主线程会始终如一地执行您告诉它要做的事情,但其他线程与这些操作中的任何一个都没有 happens-before 关系,可能不会以相同的方式看到这些动作。在你的例子中,显示了三个线程,有几个关系:
§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
的事实或者根本不终止。
因为无法保证执行顺序。在下面的程序中,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();
}
}
编辑:看到评论想补充几点
- answerReady 可能永远不会变为真。同意。
- 可以更改执行顺序的特殊情况是什么?
- 为什么 main 方法在这里正确同步?
没有。主线程上的执行顺序与您在 main
:
t1.start();
t2.start();
t1.join();
t2.join();
唯一没有保证的是线程 t1
和 t2
.
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()
的调用是同一线程的操作,因此它们按照程序顺序进行排序。
我认为,如果不存在这种简单的保证,那么很明显,即使是单线程编程也是不可能的。
这并不意味着代码中没有重新排序。它仅意味着此类优化必须以在执行此代码时保留这些操作的可观察行为的方式发生。
这里的重点是,虽然主线程会始终如一地执行您告诉它要做的事情,但其他线程与这些操作中的任何一个都没有 happens-before 关系,可能不会以相同的方式看到这些动作。在你的例子中,显示了三个线程,有几个关系:
§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
的事实或者根本不终止。