一道面试题引发的对Java内存模型的一点疑问

问题描述

如上图所示程序,按道理,子线程会通过 num++ 操作破坏 while 循环的条件,从而终止循环,执行最后的输出操作。但在我的多次运行中,偶尔会出现 while 循环一直不结束的场合。像我截图一样,程序一直不终止,JDK7、JDK8 均已试验,均能偶然触发。

回复

[西湖の风]:变量前加个 volatile。

[csyangchsh]:volatile 使用读写屏障强制刷新缓存,如果不加就由 CPU 决定何时刷新。

[sofkyle]:由 CPU 决定何时刷新,那么可以认为,终会有一个时机会去刷新,但是while卡在那一直不刷新。

[你假笨]:和 jit 也是有一定关系的,-Xint 设定解释执行,也可以只关闭 OSR 看看,-XX:-UseOnStackReplacement。

JVM STW 里的 no vm operation 是怎么发生的

问题描述

我们线上应用提供的服务接口突然超时(dubbo服务接口调用耗时最大限制1s),发现gc.log在对应的时间进入了STW,耗时1.526s查看对应的vm.log发现在相对饮的时间有一个no vm operation提示,请教下:no vm operation,这个类型vm具体在做什么操作啊?如何优化?

回复

[你假笨]:safepoint并不是一定要发生了某个VM_OP才会进入的,VMThread本身的执行,就是不断循环,看是否有必要进入safepoint,或者是否要执行一些VM_OP,可以看下这块代码。

while (!should_terminate() && _cur_vm_operation == NULL) { // wait with a timeout to guarantee safepoints at regular intervals bool timedout = VMOperationQueue_lock->wait(Mutex::_no_safepoint_check_flag, GuaranteedSafepointInterval); // Support for self destruction if ((SelfDestructTimer != 0) && !is_error_reported() && (os::elapsedTime() > SelfDestructTimer * 60)) { tty->print_cr("VM self-destructed"); exit(-1); } if (timedout && (SafepointALot || SafepointSynchronize::is_cleanup_needed())) { MutexUnlockerEx mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); // Force a safepoint since we have not had one for at least // 'GuaranteedSafepointInterval' milliseconds. This will run all // the clean-up processing that needs to be done regularly at a // safepoint SafepointSynchronize::begin(); #ifdef ASSERT if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); #endif SafepointSynchronize::end(); } _cur_vm_operation = _vm_queue->remove_next(); // If we are at a safepoint we will evaluate all the operations that // follow that also require a safepoint if (_cur_vm_operation != NULL && _cur_vm_operation->evaluate_at_safepoint()) { safepoint_ops = _vm_queue->drain_at_safepoint_priority(); } }

几个关键的点,GuaranteedSafepointInterval,timedout,SafepointSynchronize::is_cleanup_needed() 如果上面条件满足,就会发生 no vm operation 的 safepoint 操作。

通过GarbageCollectorMXBean获取到的fgc次数耗时与jstat获取到的不一致

问题描述

-XX:+UseCompressedOops -Xms5g -Xmx5g -XX:PermSize=256M -XX:MaxPermSize=1024m -XX:NewSize=3g -XX:MaxNewSize=3g -XX:+UseCMSInitiatingOccupancyOnly -XX:+PerfDataSaveToFile -XX:SurvivorRatio=10 -Xloggc:/data/dataLogs/gc/gc.log -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:CMSInitiatingOccupancyFraction=80 -XX:+HeapDumpOnOutOfMemoryError

这是我的 jvm 参数,jstat采集到的ygc次数与mxbean是一致的,fgc的数量大概是mxbean统计到的两倍,但是不到两倍。 对于耗时,jstat采集到的无论是ygc还是fgc均小于mxbean统计到的数据。

回复

[Rookie_267692]:这是因为CMS收集器在MXBean是在每次发生FGC时只会在Sweeping统计一次,而jstat会在InitialMark阶段统计一次,FinalMark阶段统计一次,这样发生一次CMS gc时就会统计两次,所以次数不一致。 gc时间在MXBen中统计的是整个gc从开始到结束时间,jstat统计的是gc在每个阶段实际耗费的时间。

推荐阅读 [ZGC什么时候会进行垃圾回收]

推荐阅读 [GC一些长时间停顿问题排查及解决办法]

一道面试题引发的对 Java 内存模型的一点疑问的更多相关文章

  1. BAT经典面试题,深入理解Java内存模型JMM

    Java 内存模型 Java 内存模型(JMM)是一种抽象的概念,并不真实存在,它描述了一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段.静态字段和构成数组对象的元素)的访问方式.试图屏 ...

  2. JVM学习(3)——总结Java内存模型

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 为什么学习Java的内存模式 缓存一致性问题 什么是内存模型 JMM(Java Memory Model)简 ...

  3. 修复 Java 内存模型,第 1 部分——Brian Goetz

    转自Java并发大师Brain Goetz:http://www.ibm.com/developerworks/cn/java/j-jtp02244/ (中文地址) http://www.ibm.co ...

  4. java内存模型个人理解总结

    现阶段线程之间的通讯主要有两种:内存共享和消息传递,而且在java中是采用的内存共享.简单说下内存共享: 假设现在有a线程和b线程,在a和b线程之间的通讯是依靠a线程将相关数据刷新到共享内存,然后b线 ...

  5. 浅谈Java内存模型

    Java内存模型虽说是一个老生常谈的问题 ,也是大厂面试中绕不过的,甚至初级面试也会问到.但是真正要理解起来,还是相当困难,主要这个东西看不见,摸不着.网上已经有大量的博客,但是人家的终究是人家的,自 ...

  6. 来,了解一下Java内存模型(JMM)

    网上有很多关于Java内存模型的文章,在<深入理解Java虚拟机>和<Java并发编程的艺术>等书中也都有关于这个知识点的介绍.但是,很多人读完之后还是搞不清楚,甚至有的人说自 ...

  7. JVM学习(3)——总结Java内存模型---转载自http://www.cnblogs.com/kubixuesheng/p/5202556.html

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 为什么学习Java的内存模式 缓存一致性问题 什么是内存模型 JMM(Java Memory Model)简 ...

  8. JVM学习记录-Java内存模型(二)

    对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用vo ...

  9. 转 Java笔记:Java内存模型

    Java笔记:Java内存模型 2014.04.09 | Comments 1. 基本概念 <深入理解Java内存模型>详细讲解了java的内存模型,这里对其中的一些基本概念做个简单的笔记 ...

随机推荐

  1. POJ3252 Round Numbers 题解 数位DP

    题目大意: 求区间 \([x,y]\) 范围内有多少数的二进制表示中的'0'的个数 \(\ge\) '1'的个数. 解题思路: 使用 数位DP 解决这个问题. 我们设状态 f[pos][num0][n ...

  2. POJ2411 Mondriaan's Dream 题解 轮廓线DP

    题目链接:http://poj.org/problem?id=2411 题目大意 给你一个 \(n \times m (1 \le n,m \le 11)\) 的矩阵,你需要用若干 \(1 \time ...

  3. 为云而生,腾讯云服务器操作系统TencentOS内核正式开源

    ​1月9日,腾讯云宣布将开源其服务器操作系统TencentOS内核.相比业内其它版本Linux 内核,腾讯云 TencentOS 内核在资源调度弹性.容器支持.系统性能及安全等层面极具竞争力,特别适合 ...

  4. 【转】在MyEclipse 8.6上搭建Android开发环境

    内容导航 第 1 页:基本环境准备 第 2 页:下载Android SDK 第 3 页:配置SDK环境变量 第 4 页:给MyEclipse安装ADT插件 第 5 页:配置MyEclipse 第 6 ...

  5. php进程 热更新

    后台启动的php守护进程时 文件内include的代码变更并未生效,需要重启进程,我们可以更新代码后手动重启.但是有些对失效要求较高.那就需要自动重启了.下面整理出三个方案用以实现. 1  inoti ...

  6. vuex使用面板报 Unexpected token错误

    Module build failed: SyntaxError: D:/frontend/webtest/src/components/mutations.vue: Unexpected token ...

  7. Python中函数参数 *args 和 **kwargs

    普通参数,即在调用函数时必须按照准确的顺序来进行参数传递. 默认参数,即参数含有默认值,在调用函数时可以进行参数传递,若没有进行参数传递则使用默认值,要注意,默认参数必须在普通参数的右侧(否则解释器无 ...

  8. 19南京网络赛A 扫描线

    题目链接:https://nanti.jisuanke.com/t/41298 扫描线的简单题,题目难在找宫殿的价值(°ー°"),比赛时将近100多行代码找价值,纯模拟,看到题解哭了. 存下 ...

  9. 【智能合约】编写复杂业务场景下的智能合约——可升级的智能合约设计模式(附Demo)

    智能合约的现状 以太坊在区块链上实现了智能合约的概念,用于:同质化通证发行(ERC-20).众筹.投票.存证取证等等,共同点是:合约逻辑简单,只是业务流程中的关键节点,而非整个业务流程.而智能合约想解 ...

  10. Java单体应用 - 导读

    原文地址:http://www.work100.net/training/monolithic 更多教程:光束云 - 免费课程 Java单体应用 本阶段课程将学习如何进行Java单体Web应用开发,经 ...