
书上说的不是很清楚,只说是编译器优化的结果。具体是什么原因呢?编译器再怎么优化 ready=true 不还得执行吗,怎么 while(!ready)就退出不了了呢?
public class NoVisibility { private static boolean ready; private static int number; private static class RaderThread extends Thread { public void run() { while (!ready); System.out.println(number); } } public static void main(String[] args) throws InterruptedException { new ReaderThread().start(); Thread.sleep(1000); number = 42; ready = true; Thread.sleep(10000); } } 1 oska874 2021-04-03 21:26:07 +08:00 while ( ready )直接优化成 while ( 1 )了,执行的时候和 ready 已经没关系了。 |
2 lsry 2021-04-03 21:31:27 +08:00 因为你 ready 在新建的线程和 main 线程中各有一个备份,在 main 线程中修改 ready 无法修改你新建线程的 ready 备份,如果让你新建的线程看到 main 修改的值,在前面加 volatile 即可。 |
3 az467 2021-04-03 21:39:14 +08:00 月经问题。。。 不是编译器优化,是 jvm 优化。 你没把 jvm 的 jit 关掉,所以 jvm 把 while (!ready); 优化成了 if (ready == false) while (true); |
4 Kasumi20 2021-04-03 21:41:49 +08:00 确实不是不是编译器优化,反编译回来是原来的代码。 那究竟是 2 楼还是 3 楼说的对呢 |
5 PythonYXY 2021-04-03 21:41:55 +08:00 建议了解下 Java 内存模型( JMM ) |
6 ipwx 2021-04-03 21:49:29 +08:00 没学过 Java,但是最近我写 C++,碰到这种多线程读写指示变量,我都是上 std::atomic 的。。。 |
8 Jooooooooo 2021-04-03 21:53:52 +08:00 搜一下 jmm 有真相. 具体说和多核 cpu 看不见其它 cpu 的值有关系 ready=true cpu1 执行完, 执行 while(!ready) 的 cpu2 看不见 |
9 yitingbai 2021-04-03 22:05:33 +08:00 2 楼的解决方案没问题, 另外我试了一下,while()中写一行代码也可以停, java 搞了这么久, 今天学到了 |
11 RicardoY 2021-04-03 22:13:48 +08:00 via iPhone 可见性 看一下 Java 内存模型 |
12 RicardoY 2021-04-03 22:15:06 +08:00 via iPhone 你 sleep 一下其实也可以 但是不知道为什么 sleep 可以 原子变量 /加锁 /volatile 是可以的 |
13 az467 2021-04-03 22:23:14 +08:00 @ignor 了解一下 JMM,你就会知道这种优化非但没有错误,反而完全是正确的。 因为变量没有被 volatile 修饰,所以 jvm 不用保证变量在线程间的可见性。 既然不用保证,那当然可以完全不保证,甚至可以反过来“保证”变量完全不可见。 这就像很多人开了 gcc 的 O3 优化,然后惊奇地发现程序运行结果跟自己预期不一致。 不好意思,是你把代码写错了。 |
14 brucewuio 2021-04-03 22:37:00 +08:00
|