gpt4 book ai didi

其他线程不可见的java实例变量

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

我在一本书中遇到过这段代码。它指出 NoVisibility 可能永远循环,因为 ready 的值可能永远不会变为读者线程可见。

我对这个说法感到困惑。为了让循环永远运行,ready 必须始终为 false,这是默认值。这意味着它必须在执行 ready = true; 时失败,因为读取器线程将始终从内存中读取 ready 变量。分配发生在 CPU 中,它在将数据刷新回主内存时一定有问题。我想我需要对它如何失败的情况进行一些解释,或者我可能错过了其他部分。

public class NoVisibility {
private static boolean ready;
private static int number;

private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}

public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}

最佳答案

你的理解有问题。您假设 Java 在这里的行为很直观。事实上,它可能不会。事实上,如果您不遵守规则,Java 语言规范允许非直观行为。

更具体地说,在您的示例中,不保证第二个线程将看到第一个线程分配给 ready 的结果。 1。这是由于以下原因:

  1. 编译器缓存 ready 的值在第一个或第二个线程的寄存器中。
  2. 编译器不包括强制将写入从一个内核的内存缓存刷新到主内存或类似内容的指令。

如果你想保证第二个线程将看到写入的结果,那么要么读写ready这两个线程必须(正确地)同步,或者 ready变量必须声明为 volatile。

所以...

This means it must fail at executing ready = true; because the reader thread will always read the ready variable from memory.

不正确。此示例中的 Java 语言规范不保证“因为”。

是的。这是不直观的。依靠你对单线程程序的理解的直觉是不可靠的。如果您想了解什么是保证和什么不是保证,请研究 JLS 的第 17.4 节中的“Java 内存模型”规范。

简而言之,这本书是正确的。


1 - 它可能会立即看到结果,或者在短暂或长时间的延迟之后。或者它可能永远看不到它们。并且这种行为很可能因一个系统和下一个系统以及 Java 平台的版本而异。因此,您的程序(幸运地)始终在一个系统上运行可能并不总是在另一个系统上运行。

关于其他线程不可见的java实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49951154/

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