Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java多线程可见性?_Java_Multithreading - Fatal编程技术网

Java多线程可见性?

Java多线程可见性?,java,multithreading,Java,Multithreading,我在一本书中读到,由于编译器优化,代码执行可能会被重新排序,从而导致ReaderThread处于无限循环中。这怎么可能 public class NoVisibility { private static boolean ready; private static int number; private static class ReaderThread extends Thread { public void run() { while (!ready)

我在一本书中读到,由于编译器优化,代码执行可能会被重新排序,从而导致ReaderThread处于无限循环中。这怎么可能

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;
    } 
}

这可能是由CPU缓存引起的。ReaderThread可能会看到“ready”变量的过期值,因此它可能不会中断while循环。过时的“就绪”值称为过时数据

这怎么可能

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语言规范(JLS)说这是可能的。然而,重新排序(可能)不会成为这里的问题。相反,无限循环可能是由于硬件内存缓存行为造成的

在这种情况下,JLS中没有任何内容要求通过
main
方法写入的变量对子线程可见。技术上的解释是,在将写操作链接到(后续)读操作之前,不会发生任何事件。如果没有关键事件发生在链之前,则无法保证可见性


注意,这里是否真的有一个无限循环将取决于各种因素。关键是,考虑到示例代码的编写方式,这是一种可能性。

为什么要投反对票?这是《Java并发操作手册》中的解释。您试过运行上述代码吗?当我使用JRE在Eclipse中运行它时,它并不是无限循环的-8@AADTechnical-那证明不了什么。底线是JLS允许代码产生无限循环。请看我的答案。@aad技术上是的,我在我的台式电脑上运行了5个读线程,它们执行得非常完美(打印42)。但我想这取决于编译器设置和CPU。这是《Java并发操作》一书中的一个例子。@StephenC是的,同意。是否有一个设置(JRE/IDE)可以让上面的代码运行到无限循环中?我不知道……谢谢你,Stephen。那么,这是否意味着子线程检查变量“ready”的副本或缓存,以便主线程的更改不可见?否则子线程不可能导致无限循环。只是好奇,这是一种可能性。另一个原因是主线程不刷新写操作。从理论上讲,没有理由不能对其他硬件架构做出其他解释。理解这一点的正确方法是从H-B关系的角度来思考。高速缓存刷新/内存障碍/任何机制都只是在某些硬件上执行程序时实现所需行为的机制。