java并发编程中的可见性问题

时间:2015-07-26 04:41:00

标签: java concurrency memory-visibility

我在“实践中的Java并发”一书中遇到了以下示例。

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

进一步说明:

  

NoVisibility可能永远循环,因为ready的值可能永远不会变为   读者线程可见。更奇怪的是,NoVisibility可以打印出来   为零,因为写入就绪可能会在之前对读者线程可见   写入数字,这种现象称为重新排序。

我可以理解重新排序问题,但我无法理解可见性问题。为什么ready的值可能永远不会对读者线程可见?一旦主线程在ready中写入值,迟早的读者线程将有机会运行,它可以读取ready的值。为什么ready中主线程所做的更改可能对读者线程不可见?

2 个答案:

答案 0 :(得分:1)

ReaderThread' run()方法可能永远不会看到ready的最新值,因为它可以自由地假设并优化该值不会在它的线程。可以通过使用该语言的相关并发功能(例如将volatile添加到ready的声明来删除此假设。

答案 1 :(得分:1)

我认为这是一个新的问题,它开始出现在多核CPU和独立的CPU缓存中。

如果您实际上正在阅读和修改内存,则无需担心,即使使用多CPU,您也可以安全,除非每个CPU现在都拥有自己的缓存。内存位置将被缓存,而另一个线程将永远不会看到它,因为它将仅在缓存中运行。

当你使它变得不稳定时,它会强制两个线程每次都直接进入内存 - 所以它会使事情变慢,但它的线程是安全的。