gpt4 book ai didi

java - Java thread.start 可以重新排序吗?

转载 作者:太空宇宙 更新时间:2023-11-04 12:25:38 27 4
gpt4 key购买 nike

考虑以下借自 Memory Consistency - happens-before relationship in Java 的场景:

package happen.before;

public class HappenBeforeRelationship {

private static int counter = 0;

private static void threadPrintMessage(String msg){
System.out.printf("[Thread %s] %s\n", Thread.currentThread().getName(), msg);
}

public static void main(String[] args) {
threadPrintMessage("Increase counter: " + ++counter);
Thread t = new Thread(new CounterRunnable());
t.start();
try {
t.join();
} catch (InterruptedException e) {
threadPrintMessage("Counter is interrupted");
}
threadPrintMessage("Finish count: " + counter);
}

private static class CounterRunnable implements Runnable {
@Override
public void run() {
threadPrintMessage("start count: " + counter);
counter++;
threadPrintMessage("stop count: " + counter);
}
}

我知道 JLS 中有一条规则保证 Thread.start 在启动线程中的所有操作之前发生。

When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.

但它并没有声明 Thread.start 之前的语句与其具有happens-before关系。

所以我想知道是否可以重新排序 Thread.start 以使程序无法获得预期的输出(counter=2)?如果不是,JLS 的哪一部分指定 Thread.start 无法重新排序?

<小时/>

另一个问题:

如果将 join() 放在 threadPrintMessage("Finish count: "+ counter); 之后会发生什么?是否有可能打印stop count: 1

最佳答案

由于 JLS§17.4.5Thread.start 调用之前的操作与新线程的启动之间存在顺序关系。 :

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
  • 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.

由于 happens-before 关系的传递性质,在调用 start() 之前主线程的操作与已启动线程内的操作之间存在 happens-before 关系。同样,启动线程的操作与主线程 join 调用的成功返回之间存在发生之前关系。

换句话说,只要您没有遇到 InterruptedException,更新就会正确排序,并且打印结果将为 2。但这并不意味着随着 JLS§17.4.5 的继续,这些操作永远不会重新排序:

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

换句话说,发生在关系是一个高级概念,它允许您确定程序执行的合法结果。如本例所示,如果程序末尾的 counter 中包含 2 是唯一合法的结果(如上所述,假设没有发生中断),那么 JVM 可能会按照自己的意愿排列代码,只要程序会产生最后的 counter 中包含 2 的合法结果。

您应该停止担心什么可以重新订购或不可以重新订购。这是一个不重要的实现细节。如果没有正确的“发生之前”关系,您可能会遇到无序的更新,而且还可能会错过更新或创建不一致的状态,因此专注于一个可能会导致损坏的程序中出现意外副作用的实现细节是没有意义的。相反,应该关注什么才是正确的程序。

关于java - Java thread.start 可以重新排序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38423556/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com