【发布时间】:2021-02-27 06:06:37
【问题描述】:
根据“Java 并发实践”一书,以下代码可能会永远执行,或者当 ready 为 true 时 number 的值可能仍为 0,建议将变量定义为 volatile。然而,即使在我多次尝试之后,下面列出的程序似乎总是返回正确的值 (42) 而不是陈旧的值。这是一种很少发生的现象吗?
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
public void run(){
System.out.println("Thread started =" + ready + " " + number);
while(!ready){
Thread.yield();
}
System.out.println("value is" + number);
}
}
public static void main(String[] args) throws InterruptedException {
new ReaderThread().start();
Thread.sleep(10000);
number = 42;
ready = true;
}
}
【问题讨论】:
-
你得到的输出是什么,你期望的输出是什么?
-
我希望循环不会结束或显示 0。但我得到 42 作为输出。
-
好吧,当您在 ReaderThread 中调用 Thread.yield() 时,它允许主线程首先运行。主线程等待 10000 英里,然后更改这两个变量。并且还终止子线程。我看不出这里有什么意外
-
我尝试使用循环和多线程,也无法让它搞砸。我想这需要被解释为“不要使用类字段进行进程间通信”,并举例说明要避免什么样的事情,即使在这个简单的情况下以及使用更新的 JVM 所提供的代码也可以正常工作。
-
@Dennishofken 根据本书,您不能确定 ReaderThread 是否会“看到”实例变量的更新值,从而导致无限循环。即使它看到更新的值,也可能在将 number 设置为 42 之前将 ready 设置为 true 的情况。因此,这可能导致 value 被打印为 0。通过同步或设置实例来做到这一点的安全方法在此特定示例中,字段为 volatile。
标签: java multithreading concurrency java.util.concurrent