gpt4 book ai didi

java - 为什么线程在不同的运行方法体中表现不同?

转载 作者:搜寻专家 更新时间:2023-10-31 19:54:37 25 4
gpt4 key购买 nike

此代码来自 Effective Java(第 66 项):(没有同步或 volatile ,这永远不会结束)

public class ThreadPractice {
static boolean canrunstatic;

public static void main(String[] args) throws InterruptedException {

Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}

正如 Bloch 在该章中提到的那样,它永远不会将“完成”写入控制台。我一直在玩这个类,并将该行添加到可运行的运行方法中:

System.out.println("im still running");

有了这个,while 循环不仅会增加 i,还会在每个循环中打印出这个字符串。但是让我发疯的是,当主线程从 sleep 中恢复时,线程会在 1 秒后停止。

已修改:(在没有 volatile/sync 的情况下停止)

public class ThreadPractice {
static boolean canrunstatic;


public static void main(String[] args) throws InterruptedException {

Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;System.out.println("im still running");}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;


}

那么这背后的逻辑是什么?

最佳答案

准确地说,只是不能保证线程永远会停止,但并不禁止它确实会停止。这背后的逻辑由 Java Memory Model 提供。 ,这是一个相当复杂的话题,但是为了理解 Java 中的多线程是需要的。

这个概念是,只有当这两个操作彼此同步时,才需要对一个线程的非 volatile 字段进行写入才能被另一个线程看到。如果执行它的线程表现出的行为没有改变,则允许编译器对某些操作重新排序。但是另一个线程可能会看到这个。因此,您需要适当的同步,以便告诉编译器某些部分不允许重新排序。

在此处阅读有关此内容的完整论文:JSR-133

关于java - 为什么线程在不同的运行方法体中表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28544248/

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