JAVA GC - STW

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

情况一: 该回收的没回收

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

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

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

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

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

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

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

你可能感兴趣的:(java,GC)