性能问答>一道面试题引发的对Java内存模型的一点疑问,第二部。>
12回复
3年前

一道面试题引发的对Java内存模型的一点疑问,第二部。



环境信息如下:
JDK版本:1.8.0_251
JDK版本.png

java.vm.version=25.251-b08
java.vm.vendor=Oracle Corporation
java.vm.name=Java HotSpot™ 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.runtime.version=1.8.0_251-b08
os.arch=amd64
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.vm.info=mixed mode

操作系统信息:
电脑版本.png

原问题
基于原来的问题,我又发现一个很奇怪的现象。

第一个问题:
如图
问题.png

第二个问题:
按照我的理解,这个程序如果Main线程在num=0时候先执行了while()循环,然后子线程再对num进行加1操作,肯定会出现死循环的情况。因为JMM规定普通的共享变量存在于主内存当中,然后每个线程都有自己的工作内存,每个线程用到变量的时候会先从主存中复制一份到自己的工作内存。就你这程序来说,如果Main线程在num=0时候先执行了while()循环,这个时候Main线程会把num的值复制一份到自己的工作内存,然后Main线程的while循环就只会读线程工作内存的副本。接下来子线程开始运行,子线程先把num的值复制一份到子线程的工作内存里面,然后对num进行加1操作,然后子线程运行结束把num刷新到主存里面。注意,即使此时子线程把num的最新值刷新到主存中,Main线程的while循环也不会结束,因为Main线程只会读自己的工作内存里面num的值,Main线程的工作内存里面的num现在还是0啊。
你的num没有用volatile修饰,所以Main线程里面的num不会失效。
(请大顺便解释一下我这个疑惑,就上面加粗这行的疑惑。)
所以,我觉得你这个程序只要Main线程在num=0时候先执行了while()循环,然后子线程再对num进行加1操作,即使没有jit的激进编译,也肯定会出现死循环的情况。

不过我发现我上面的说法也不对。我发现加了-Xint参数之后,就肯定不会出现死循环了。这是为什么呢?难道加了-Xint参数之后,Main线程每次循环的时候都会去主存中读取num的值吗?这跟JMM规定的不太一样啊?JMM规定普通的共享变量存在于主内存当中,然后每个线程都有自己的工作内存。

6736 阅读
请先登录,查看12条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步