《JAVA并发编程实战》上面的一个问题
《JAVA并发编程实战》上面的一个问题讲可见性的时候举了一个例子:publicclassNoVisibility{privatestaticbooleanready;pr...
《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;
}
}
说这段代码可能一直循环下去,因为读线程可能一直看不了ready的值,可见性我大概了解了,可能主线程上对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;
}
}
说这段代码可能一直循环下去,因为读线程可能一直看不了ready的值,可见性我大概了解了,可能主线程上对ready的修改是没及时提交到主存,但是也总还是会提交的吧,那也不会导致读进程一直循环吧,谁能告诉我一下到底怎么回事 展开
2个回答
展开全部
总共就三种情况!!!!1.无限循环,number的值为0:在主线程即main方法中对ready的设置(即ready = true)还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了ready的值(并保留了副本),然后加载到Java栈中,此时ready 一直为false所以出现死循环。number的值也可以类似推理,在主线程即main方法中对number的设置(即number= 42)还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了number的值(并保留了副本),然后加载到Java栈中,此时number一直为0(只是没有打印出来而已);
2.无限循环,number的值为42:在主线程即main方法中对ready的设置(即ready = true)还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了ready的值(并保留了副本),然后加载到Java栈中,此时ready 一直为false所以出现死循环。在主线程即main方法中对number的设置(即number= 42)后(即number的值已经写回了主存),ReaderThread 线程才开始执行此时读取的number为42(只是没有打印出来而已);
3.输出0:在主线程即main方法中对ready的设置(即ready = true)后(即ready的值已经写回了主存),还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了number的值(并保留了副本),然后加载到Java栈中,此时number为0;
至于为什么会出现ready = true写回主存后,number = 42还没写回主存。这应该是由于Java虚拟机的一种优化技术叫指令重排序,number = 42不一定会在ready = true前面执行,得看Java虚拟机是怎么优化的。
2.无限循环,number的值为42:在主线程即main方法中对ready的设置(即ready = true)还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了ready的值(并保留了副本),然后加载到Java栈中,此时ready 一直为false所以出现死循环。在主线程即main方法中对number的设置(即number= 42)后(即number的值已经写回了主存),ReaderThread 线程才开始执行此时读取的number为42(只是没有打印出来而已);
3.输出0:在主线程即main方法中对ready的设置(即ready = true)后(即ready的值已经写回了主存),还没来得及写回主存(静态变量保存在方法区),ReaderThread 线程就已经读取了number的值(并保留了副本),然后加载到Java栈中,此时number为0;
至于为什么会出现ready = true写回主存后,number = 42还没写回主存。这应该是由于Java虚拟机的一种优化技术叫指令重排序,number = 42不一定会在ready = true前面执行,得看Java虚拟机是怎么优化的。
更多追问追答
追问
它每次循环之前不是都会判断一次ready么,即使主线程没来的及写到主存,但总还是会有个时间写到主存然后读线程循环的时候判断为真结束循环啊
我看到的比较又说服力的是说JVM在server模式下的优化措施有一个是把循环中没有改变的值提到循环外,所以那个ready的判断只在循环外判断了一次
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询