看到了两篇文章很有意思,记录一下。
https://zhuanlan.zhihu.com/p/461298916
https://mp.weixin.qq.com/s/KDUccdLALWdjNBrFjVR74Q
总之对于这两篇文章所产生的问题的原因是因为:
线程1,线程2中是两个十分耗时的循环,且是counted loops。因为是counted loops,所以并不会在每次会跳之前放置安全点。
JVM只有在进入安全点之后才能周期性的停止用户线程(如做清理垃圾工作)。
而Thread.Sleep使主线程进入安全区域,最后当Thread.sleep睡醒时(也就是从native方法返回时)又需要检查其他线程是否已经跑到安全点,如果没有跑到安全点,此时它就会继续挂起。
而这段代码由于是counted loops,不会设置安全点。这就导致,由于这两个线程没有进入安全点而无法停止。对于主线程来说,就是无法离开安全区域,则会把自己挂起,等待被唤醒。
安全点:安全点是为JVM进行GC操作时,触发Stop the world而设置的。
安全区域:
Safe Point 是对正在执行的线程设定的。如果一个线程处于 Sleep 或中断状态,它就不能响应 JVM 的中断请求,再运行到 Safe Point上。
因此 JVM 引入了 Safe Region。
Safe Region 是指在一段代码片段中,引用关系不会发生变化。在这个区域内的任意地方开始 GC 都是安全的。
线程在进入 Safe Region 的时候先标记自己已进入了 Safe Region,等到被唤醒时准备离开 Safe Region 时,先检查能否离开,如果 GC 完成了,那么线程可以离开,否则它必须等待直到收到安全离开的信号为止。
参考:https://blog.csdn.net/weixin_29051149/article/details/114614008