java stw_聊聊JAVA GC系列(6) - STW

上回介绍了"平平无奇"的标记清除算法却是JAVA GC的灵魂, 介绍的过程中留下了几个问题, 其中一个问题是: 标记清除算法正在运行时各个对象的依赖关系发生了变化怎么办?

我们先假设GC拥有独立的线程, 与用户的逻辑并行的运行, 看看会有哪些不符合预期的情况.

情况一: 该回收的没回收

在标记的过程中, 在对象被标记之后, 用户的线程做了一些操作, 所有对象都不再依赖这个对象了, 那么这个对象应该被回收, 但是在这次遍历中不会被回收了

情况二: 不该回收的回收了

在标记的过程中, 用户的线程又创建一些新对象, 并且与旧的对象存在一些依赖关系, 但是依赖这些对象的旧对象在这次标记中都已经被遍历过了, 也就是说这些新产生的对象在这次的遍历过程中不会被标记了, 那么它们应该会被标记为可回收的对象, 然后就被回收掉了.对于情况一: 该回收的没回收还是能忍的, 因为下次遍历时就能进行回收了

对于情况二: 不该回收的回收了是没有办法忍的, 因为明明用户逻辑还需要的对象就直接被回收了, 会导致出错.

先分析一下这两种情况产生的原因——都是由于GC线程与用户逻辑并行运行导致的. 那么应该怎么解决这个问题呢?

聪(糊)明(弄)伶(老)俐(板)的开发者想到了一个简单粗暴的解法: 让GC线程和用户逻辑的线程不要同时运行, 先运行用户逻辑的线程, 运行到需要GC的时候, 就把所有用户逻辑的线程给停住, 然后启动GC线程去进行标记清除, 在GC线程标记清除运行结束后, 再继续进行用户逻辑的线程. 这种方法就是大名鼎鼎的STW (Stop-The-World, 意思是在GC的时候停下用户逻辑的全世界).

STW本质是通过把GC和用户逻辑搞成串行的方法, 来避免上面的两种并发可能会导致的问题. 但是它引入了一个很大的代价, 就是会停止用户逻辑的运行一段时间, 举个例子, 用户逻辑是一个JAVA的网站的服务, 那么一旦它开始进行GC后就不再接受用户的请求了, 这个网站在这段时间内就是不可用(不响应任何请求)的状态. 也正是因为这个STW的特点, 让追求极致可用性的开发者都转入了C/C++阵营.

在结束这篇文章之前, 再问个问题: GC是不是一定要STW?

虽然即使目前最优秀的垃圾回收器的实现还是需要STW的(尽管已经优化到了非常短暂的时间), 但是我依然相信未来的某一天, 会出现完全不需要STW的垃圾回收器. 因为随着屏障技术越来越细致, 我相信最终会迎来某个时间, GC的线程是完全和用户线程并行运行的, 当然这需要用户的逻辑满足一些特定的条件才能达到, 关于这块的讨论, 后续再继续填坑.

下篇介绍: 聊聊JAVA GC系列(7) - 标记整理算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值