gpt4 book ai didi

线程中的 Java 指令重新排序/缓存

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:40:35 25 4
gpt4 key购买 nike

读一本书,出现这段代码:

public class Test {

private static boolean ready = false;
private static int number = 0;

public static class ListenerThread extends Thread {

public void run() {

while(!ready) {
Thread.yield();
}
System.out.println(number);

}

}

public static void main (String[] args) {

new ListenerThread().start();
number = 10;
ready = true;

}

}

作者比较快地提到了我感到惊讶的要点。

  1. 他们说 ListenerThread 可能永远不会终止。我考虑了几天(在脑海中),我唯一的结论是它可能被那个 ListenerThread 缓存了。真的吗?将 ready 设置为 volatile 可以解决问题(因为它不应该再缓存它了)吗?

  2. 他们还说该程序可能会打印 0。我现在明白 Java 可能会重新排序指令,因此在更改数字之前,准备就绪对另一个线程变为真。除了将这些指令放在同步块(synchronized block)中之外,还有什么方法(技术)可以解决问题(在中央锁值上)?我在想也许可以实现 notify()/wait(),但我觉得它会遭受同样的后果。避免该问题的最佳方法是什么?

谢谢!

编辑:

我只是觉得我已经通读了很多代码,很少有人费心去防止在多线程中重新排序。这有多普遍?

最佳答案

my only conclusion is that it might be cached by that ListenerThread. Is that true? Would making ready volatile solve the problem (since it shouldn't cache it anymore)?

不仅缓存,而且 JIT 可以在线程永远不会更改它的基础上内联该值。即它变成了硬编码。

使用 volatile 可以防止做出此类假设。它将强制它每次读取缓存一致的副本。

I understand now that Java might reorder the instructions,

不仅是Java,CPU也可以对指令进行重新排序。 JIT 知道 CPU 可以进行这种重新排序,而且据我所知,它很少需要这样做,因为它假定 CPU 会做得很好。

顺便说一句,访问 volatile 变量也可以防止指令重新排序,因此使 ready volatile 可以解决这两个问题。

关于线程中的 Java 指令重新排序/缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14321212/

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