关于“Java 并发实践”示例的问题

2022-09-01 18:27:31

我正在查看Brian Goetz的“Java Concurrency in Practice”中的代码示例。他说,这段代码可能会停留在无限循环中,因为“'ready'的值可能永远不会对读者线程可见”。我不明白这是怎么发生的...

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

答案 1

因为 未标记为,并且值可能会在循环开始时缓存,因为它在循环中未更改。这是抖动优化代码的方法之一。readyvolatilewhilewhile

因此,线程可能在本地启动并读取该线程的缓存,并且永远不会再次读取它。ready = trueready = false

查看易失性关键字


答案 2

原因在代码示例后面的部分中进行了说明。

3.1.1 陈旧数据

NoVisibility演示了未充分同步的程序可能导致令人惊讶的结果的方式:陈旧的数据。当读者线程检查时,它可能会看到一个过时的值。除非每次访问变量时都使用同步,否则可能会看到该变量的过时值。ready


推荐