MST

星途 面试题库

面试题:缓存设计:常见内存缓存垃圾回收算法的特点

请简要介绍至少两种常见的内存缓存垃圾回收算法,如标记 - 清除算法、引用计数算法等,并阐述它们各自的特点及适用场景。
45.2万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

标记 - 清除算法

  1. 算法描述
    • 首先标记出所有需要回收的对象,一般通过从根对象(如全局变量、栈上的变量等)出发,遍历所有可到达的对象,未被遍历到的对象即为需要回收的对象。
    • 标记完成后,统一回收所有被标记的对象。
  2. 特点
    • 优点:实现简单,不需要额外的空间记录引用计数。
    • 缺点
      • 效率问题,标记和清除两个过程的效率都不高,标记阶段需要遍历所有对象,清除阶段需要遍历堆内存空间。
      • 产生内存碎片,清除后会在内存中留下不连续的空闲区域,可能导致后续大对象无法分配到足够连续的内存空间。
  3. 适用场景:适用于对象生命周期较长、内存分配和回收频率较低的场景,例如一些服务器端应用,对内存碎片不太敏感,更注重实现的简单性。

引用计数算法

  1. 算法描述: 为每个对象设置一个引用计数器,每当有一个地方引用该对象时,计数器加1;当引用失效时,计数器减1。当计数器的值为0时,该对象就可以被回收。
  2. 特点
    • 优点
      • 回收及时,只要对象的引用计数为0,就可以立即回收,不会像标记 - 清除算法那样需要等待一个完整的回收周期。
      • 实时性较好,在对象引用变化时就进行计数调整,不会出现长时间的卡顿。
    • 缺点
      • 维护引用计数的开销较大,每次引用关系变化都需要更新计数器,增加了系统开销。
      • 无法解决循环引用问题,若两个或多个对象相互引用,即使它们与根对象没有连接,其引用计数也不会为0,导致无法回收。
  3. 适用场景:适用于短生命周期对象较多、对实时性要求较高且不容易出现循环引用的场景,比如一些游戏开发中对短期使用的对象管理。

复制算法

  1. 算法描述
    • 将内存分为两块大小相等的区域,每次只使用其中一块。当这一块内存使用完后,将存活的对象复制到另一块空闲区域,然后把使用过的区域一次性清理掉。
  2. 特点
    • 优点
      • 简单高效,只需复制存活对象,清除操作简单,不会产生内存碎片。
      • 适合回收大量短生命周期对象,因为复制操作相对标记 - 清除算法效率更高。
    • 缺点
      • 内存利用率低,始终只有一半的内存可用,另一半作为备用空间。
      • 复制操作对长生命周期对象开销大,每次回收都要复制存活的长生命周期对象。
  3. 适用场景:适用于新生代内存区域,新生代中对象大多生命周期短,适合使用复制算法提高回收效率。例如Java虚拟机的新生代垃圾回收就常采用类似复制算法的策略。

标记 - 整理算法

  1. 算法描述
    • 首先标记出所有存活的对象,与标记 - 清除算法的标记阶段类似。
    • 然后将存活的对象向内存的一端移动,最后清理掉边界以外的内存空间。
  2. 特点
    • 优点
      • 解决了标记 - 清除算法产生内存碎片的问题,通过移动存活对象保证内存的连续性。
      • 对于老年代这种对象存活率高的场景,相较于复制算法,避免了大量对象的复制操作,提高了效率。
    • 缺点
      • 移动对象的操作需要调整对象的引用地址,开销较大。
      • 标记和整理过程效率相对不高,标记阶段要遍历所有对象,整理阶段要移动存活对象。
  3. 适用场景:适用于老年代内存区域,老年代中对象存活率高,需要避免内存碎片,同时对效率要求不是极端苛刻,标记 - 整理算法可以较好地满足需求。