【新,Java多线程面试题大全含答案

这种循环称为“counted loop”,就是有明确的循环计数器变量,而且该变量有明确的起始值、终止值、步进长度的循环。

它有可能被优化为循环末尾没有 safepoint,于是如果这个循环的循环次数很多、循环体里又不调用别的方法或者是调用了方法但被内联进来了,就有可能会导致进入 safepoint 非常耗时。

可惜的是现在没什么特别方便的办法直接指出是什么地方有这种循环。有的话,一种解决办法是把单层循环拆成等价的双重嵌套循环,这样其中一层循环末尾的 safepoint 就可能会留下来,减少进入 safepoint 的等待时间。

如何判断内联方法


从代码角度如何判断方法被内联进来了,主要是方法被 final 修饰。 final 是可以帮助 JIT 编译器做出内联的判断,但不是必要条件。

  • -XX:+PrintCompilation -XX:+PrintInlining 来看内联状况

  • -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1 ”输出的结果“[time: spin block sync cleanup vmop] ”中 spin 是指什么呢?

  • PrintSafepointStatics:打印出来的 spin 值指的是 SafepointSynchronize 在同步每个线程时做的自旋。

thread locking / biased locking 的 spin 完全没关系,自然设置那些参数也不会影响 safepoint 的自旋(UseSpinning 之类控制的是 thread locking 的自旋)。

SafePoint 存在的目的?


为什么把这些位置设置为 jvm 的安全点呢,主要目的就是避免程序长时间无法进入 safepoint,比如 JVM 在做 GC 之前要等所有的应用线程进入到安全点后 VM 线程才能分派 GC 任务 ,如果有线程一直没有进入到安全点,就会导致 GC 时 JVM 停顿时间延长。

比如,写了一个超大的循环导致线程一直没有进入到安全点,GC 前停顿了 8 秒。

产生的日志信息基本上 STW 的原因都是 RevokeBias 或者 BulkRevokeBias。这个是撤销偏向锁操作,虽然每次暂停的时间很短,但是特别频繁出现也会很耗时。

GC 如何找到不可用的对象

编写代码的时候是可以知道对象不可用的,但对于程序来说,需要一定的方式来知晓,可用方法比如:编译分析,引用计数,和对象是否可达。

可达性分析

因而可达性分析,只需要找到直接可达的引用,直接可达的引用就是根引用,根引用的集合就是根的集合

  1. 一个对象只要能够通过 mutator 触达,那么它就是“活”着的。

  2. 如果 Mutator 栈的一个槽位包含了对象的引用,那么对象就是直接可触达。

  3. 从直接可达对象可触达的对象必定也是可达的,

muator 线程分析

  • mutator 的上下文就包含了直接可达的数据,所以要获取对象根集合就是要找到 mutator 上下文中的对象引用,

  • mutator 的上下文指的就是它的栈、它的寄存器文件以及一些线程上特定的数据。

静态数据


全局数据本身也是直接可达的

可达性分析为了确保能正确的决定对象是否存活,GC 需要获取 mutator 上下文的(当前)一致性快照,然后枚举所有的根对象。

  • 一致性指的是:快照的抽取就像只在一个时间点发生,来避免丢失一些活着的对象。

如何获取 mutator 上下文的一致性快照

一种简单的方式就是在跟引用的过程中暂停所有的线程。当 mutator 暂停了它的执行时,只有将所有引用信息保存在其上下文中,才能枚举根的集合,这意味着,mutator 需要能够告诉 JVM 哪些栈的槽位有用,哪些寄存器持有引用。

如果 GC 能够准确的获取上述引用信息,它就称作精准根集合枚举。而无法获取就是不精准的。

如何获取精准的引用信息枚举


对于 java 来说,JIT 知晓所有的栈帧信息和寄存器的内容,当 JIT 编译一个方法时,对于每条指令,它都可以去保存根引用信息,保存意味着额外的存储空间,如果要存储所有的指令就显得花销太大,另外在真实的运行过程中也只有少数指令才会成为暂停点,因此 JIT 只需要保存这些指令点的信息就够了。而真正有机会成为暂停点的地方就称作 safe-points,即能够安全的枚举根集合的暂停点

如何保证 mutator 会在 safe-point 暂停


当 GC 想要触发一次回收时,它会设置一个标志,mutator 则周期性的去检查(poll)这个标志,如果检查到了,就会立马暂停,这里的检查点(poll points)也是安全点,由 JIT 负责把 poll points 放到合适的位置,那些地方适合设置检查 GC 事件的标记

polling point 插入的主要原则是:

  • polling point 应该足够多,防止 GC 等一个 mutator 的暂停太长,导致其他 mutator 都走在等 GC 释放空间,程序整个等待过长

  • polling point 不能太频繁导致运行时存储开销过大

  • polling 本身也是有开销的,不能过多

  • 权衡下来只在必须和必要的地方加

  • 分配地址的时候强制添加,因为分配空间很有肯能导致回收,所以这里是一个安全点

  • 长时间的执行一般意味着循环和方法调用,所以方法调用和循环返回最好加上

但是有时候并不是长时间的执行,而是长时间的空闲,比如 sleep、block,线程在执行其他的 native 函数,这些时候 JVM 无法掌控执行能力,也就无法响应 GC 事件。

SafePoint 无法解决 sleep/block 带来的问题,当这段时间内 JVM 要发起 GC 时,就不管没到安全点但是在安全区域的线程。在线程要离开安全区域时,要检查系统是否已经完成了 GC,故我们又定义了一个安全区域的概念.

SafeRegion 的简介


safe-region 是指代码快中没有用到会变异的部分,这样的代码块中,任何一个点都可以安全的枚举根。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(img-4po7TzhW-1710851953053)]
[外链图片转存中…(img-i9G8Mugw-1710851953053)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-bW9KdiHC-1710851953054)]

  • 25
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值