线程
大约 4 分钟
这里所说的线程指的是程序执行过程中的一个线程实体。JVM 允许一个应用执行多个线程。Hostpot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系。
Hotspot JVM 后台运行的系统线程主要有下面几个:
系统线程 | 描述 |
---|---|
虚拟机线程(VM Thread) | 这个线程等待 JVM 到达安全点操作才会启动。这些操作必须要在独立的线程里执行,因为当堆修改无法进行时,线程都需要 JVM 位于安全点。这些操作的类型有:stop-the-world 垃圾回收、线程dump、线程暂停、线程偏向锁(biased locking)接触。 |
周期性任务线程 | 该线程主要负责定时器事件(中断),用来调度周期性操作的执行。 |
GC 线程 | 这些线程支持 JVM 中不同的垃圾回收活动。 |
编译器线程 | 这些线程在运行时将字节码动态编译成本地平台相关的机器码。 |
信号分发线程 | 这个线程接收发送到 JVM 的信息并调用适当的 JVM 方法处理。 |
什么是 JVM 安全点(Safe Point)
程序在执行时并非所有地方都能停顿下来开始 GC,只有在特定位置停顿下来才能开始 GC,即垃圾回收;这些特定的位置就称之为“安全点(Safe Point)”。
安全点的选择
安全点的选择很重要,如果安全点选择太少,会导致 GC 等待事件太长;过多会导致系统负荷变大,性能降低。由于大部分指令的执行时间都非常短暂,通常会根据“是否具有让程序长时间执行的特征”为标准。比如:选择一些执行时间较长的指令作为安全点(Safe Point),如:
- 循环的末尾
- 方法临近返回前
- 调用方法之后
- 抛出异常的位置
GC 线程的终端策略
当 GC 发生时,我们应该如何检测所有的线程都跑到了最近的安全点停顿下来了呢?
- 抢先式中断(目前没有虚拟机再采用该策略了):中断所有线程,当有线程不在安全点,就恢复线程,让线程跑到安全点。
- 主动式中断:设置一个中断标志,各个线程运行到安全点的时候就主动轮询这个标志,如果中断标志为 true,则将自己当前线程进行中断挂起。(举例:客栈(安全点)门上安装了一个显示器,上面会显示 true,或者 false;当系统需要进行垃圾回收的时候,将更新显示 true,此时就是告诉线程进入客栈之后就不要出来了。)
安全区域 Safe Region
Safe Point 机制保证了程序执行时,在不太长的时间内就会遇到可进入 GC 的 Safe Point。但是,程序“不执行”的时候呢?例如线程处于 Sleep 状态或 Blocked 状态,这时候线程无法响应 JVM 的中断请求,“走”到安全点去中断挂起,JVM 也不太可能等待线程被唤醒。对于这种情况,就需要安全区域(Safe Region)来解决。
安全区域是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始 GC 都是安全的。我们也可以把 Safe Region 看做是被扩展了的 Safe Point。
安全区域 Safe Region 执行流程
实际执行时:
- 当线程运行到 Safe Region 的代码时,首先标识已经进入了 Safe Point,如果这段时间内发生 GC,JVM 会忽略表示为 Safe Region 状态的线程(即认为该线程是安全的)
- 当线程即将离开时,会检查 JVM 是否已经完成了 GC,如果完成,则继续运行,否则线程必须等待直到收到可以安全离开 Safe Region 的信号为止。
摘抄自:https://blog.csdn.net/fsjwin/article/details/109235471