GC(垃圾回收)必须Stop-the-world?html
并发编程的许多困难都源于对象生存期问题,当对象在线程之间传递时,要确保它们安全地释放就变得很麻烦。所以GC可使得并发编程变得容易。可是实GC也是一个挑战,可是一次实现,就能够解决人们手动管理内存的麻烦(C语言),大大提升的开发效率和避免了许多Bug。java
可是GC也是有成本的,他会影响程序的效率,GC是一个很是挑战的工做,不少计算机科学家在上面耗费了数十年不断的提高效率。算法
GC算法设计时,会考虑几个重要指标:编程
不少人问为何GC的时候要暂停(Stop-the-world)整个程序,为何不能并发的执行GC呢?GC本质上是一种权衡,Stop-the-world 是为了GC吞吐量(在给定CPU时间内多少垃圾能够被收集器清除?),便不是说GC必须STW,你也能够选择下降运行速度可是能够并发执行的收集算法,这取决于你的业务。安全
J9VM中标记阶段有描述,标记分为:bash
并行标记的目的是在不下降单处理器系统上标记性能的状况下,提升多处理器系统上典型标记的性能。
经过增长共享使用工做包池的助手线程,能够提升对象标记的性能。例如,可选取由一个线程返回给池的完整输出包做为另外一个线程的新输入包。
并行标记仍须要一个用做主协调代理进程的应用程序线程的参与。助手线程帮助标识回收的根指针并跟踪这些根。标记位是使用不须要附加锁的主机原子原语来更新的
复制代码
在堆大小增长时,并发标记可以提供缩短且一致的垃圾回收暂停时间。
在堆满以前,GC 将启动并发标记阶段。在并发阶段,GC 扫描堆,检查根对象,好比堆栈、JNI 引用和类静态字段。经过要求每一个线程扫描本身的堆栈来扫描堆栈。随后,这些根将用于并发跟踪活动对象。在线程执行堆锁分配时,跟踪由低优先级的后台线程和每一个应用程序线程执行。
当 GC 利用正在运行的应用程序线程并发标记活动对象时,必须记录对已跟踪对象的任何更改。它使用在每次更新对象中的引用时运行的写屏障。在发生对象引用更新时,写屏障将使用标志。使用该标志迫使对部分堆从新扫描。
复制代码
好比:你作金融交易类的项目,分秒必争,那能够选择并行的方式。若是你是一种后台任务,好比数据处理,那你能够选择STW类型算法,使 GC 的吞吐量获得最高。markdown
两类算法最终的权衡指标就GC效率:程序工做时间与执行收集时间的比率。并发
没有单一的算法在全部方面都完美,语言也不可能知道程序的业务类型,这也就是“GC调优”存在的缘由。这也是科学的基础规律。oop