多线程间,变量可见性问题。一个线程会永远看不到另一个线程的更新吗?

作者说,由于读线程可能永远发现不了main对ready变量的修改就会永远循环下去,但是貌似不太可能永远读不到main对ready变量修改之后的值吧,可能会由于从栈区复制回堆区时,有几毫秒的误差,read线程读到的是旧值,但堆区值更新之后,read线程就读到了新值了吧,为什么说会永远循环下去呢?图片说明

5个回答

再回去又读了一遍,有如下解释:
根据JVM设置,如果设置成server模式会有指令重排,如上述循环判断就会变成if(!ready){while(true){...}}所以就会造成死循环,如果设置成volatile,JVM就不会对这个变量进行指令重排。

qq_30680953
qq_30680953 还是无法出现无限循环的样子,理论上的原因是知道了。无法实践。
4 年多之前 回复

亲测,线程是能读取到ready值的改变的,可以正常的结束
并且,看代码没有问题啊,应该不会出现读取不到ready值改变的情况的,一般通过旗标来关闭线程都是这样来操作的。

daidaineteasy
晓呆同学 回复qq_30680953: 嘿嘿,也是对这上面说的内容感到疑惑,所以就自己动手试了试。因为之前一直用ready这种的旗标来退出线程,这上边说可能会永远读不到,所以就想看看啥情况。
4 年多之前 回复
qq_30680953
qq_30680953 给力。。。忘了贴代码给大家测试了,谢谢。。
4 年多之前 回复

附上测试代码

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并发编程实践 第三章开头的一个例子,是并发编程的经典教材,按道理作者应该不会说错。
但是为何我在jdk1.7下出来的结果,以及根据我的理解,都不太可能永远死循环。
求合理解释

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐