gpt4 book ai didi

java - 为什么这段代码没有像 JSR133 所建议的那样进入无限循环?

转载 作者:行者123 更新时间:2023-11-30 05:43:07 25 4
gpt4 key购买 nike

JSR-133 section 3.1 ,它讨论了线程之间操作的可见性 - 提到下面的代码示例,它没有使用 boolean 字段的 volatile 关键字,如果两个线程正在运行它,它可能会变成无限循环。以下是 JSR 中的代码:

class LoopMayNeverEnd {
boolean done = false;
void work() {
while (!done) {
// do work
}
}
void stopWork() {
done = true;
}
}

以下是我感兴趣的该部分中重要部分的引用:

... Now imagine that two threads are created, and that one thread calls work(), and at some point, the other thread calls stopWork(). Because there is no happens-before relationship between the two threads, the thread in the loop may never see the update to done performed by the other thread ...

这是我自己编写的 Java 代码,这样我就可以看到它循环:

public class VolatileTest {
private boolean done = false;
public static void main(String[] args) {
VolatileTest volatileTest = new VolatileTest();
volatileTest.runTest();
}
private void runTest() {
Thread t1 = new Thread(() -> work());
Thread t2 = new Thread(() -> stopWork());
t1.start();
t2.start();
}
private void stopWork() {
done = true;
System.out.println("stopped work");
}
private void work() {
while(!done){
System.out.println("started work");
}
}
}

尽管连续执行的结果不同 - 正如预期的那样 - 我没有看到它进入无限循环。我试图了解如何模拟文档建议的无限循环,我错过了什么?如何声明 boolean 值 volatile ,消除无限循环?

最佳答案

实际行为是特定于操作系统和 JVM 的。例如,默认情况下,Java 在 32 位 Windows 上以客户端模式运行,在 Mac 上以服务器模式运行。在客户端模式中,work方法将终止,但在服务器模式中不会终止。

出现这种情况是因为 Java 服务器 JIT 编译器优化。 JIT 编译器可能会优化 while 循环,因为它看不到变量 done 在线程上下文中发生变化。无限循环的另一个原因可能是因为一个线程最终可能会从其寄存器或缓存中读取标志的值,而不是进入内存。因此,它可能永远不会看到另一个线程对此标志所做的更改。

本质上,通过添加 volatile ,您可以使拥有done标志的线程不缓存该标志。因此, boolean 值存储在公共(public)内存中,从而保证可见性。此外,通过使用 volatile ,您可以禁用可以内联标志值的 JIT 优化。

基本上,如果您想重现无限循环 - 只需在服务器模式下运行您的程序即可:

java -server VolatileTest

关于java - 为什么这段代码没有像 JSR133 所建议的那样进入无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55322624/

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