当前位置: 首页 > article >正文

谈谈我的理解:引用计数 vs 可达性分析

前言

在学习垃圾回收机制时,首先需要了解如何判定哪些对象需要被回收,以及如何实现垃圾回收。本文将分享作者对两种常见的垃圾回收判断机制——引用计数法和可达性分析法——的理解与思考,旨在帮助读者更深入地理解这两种机制。

一、引用计数法

1.1、介绍

引用计数法为每个对象维护一个引用计数,表示有多少个引用指向该对象。当引用计数变为零时,表示该对象不再被使用,可以被回收。

1.2、优缺点分析

1.2.1、优点
  • 实时性:当对象的引用计数降为零时,立即释放内存,能够迅速回收不再使用的对象。

  • 简单易实现:实现相对简单,适合需要低延迟的应用场景。

1.2.2、缺点
  • 循环引用问题:如果两个或多个对象相互引用,引用计数无法正确回收这些对象,导致内存泄漏。

  • 额外开销:每次引用或取消引用时都需要更新计数,增加了额外的性能开销。

  • 内存 碎片问题:频繁的分配和释放内存可能导致内存碎片化。

1.3、循环引用问题的解决

普通引用计数法肯定是有循环引用问题的,但是也可以采取相应的措施来解决这个问题,在此,我们来介绍两种实现方式:

例如:

  1. 通过维护额外的“访问计数”或“引用链”来记录对象的引用关系,并将垃圾回收分两个阶段,首先是普通引用计数回收,第二阶段则是检查剩余对象是否存在循环引用。

    image-20241015164434454

  2. 也是维护额外“访问计数”或“引用链”来记录对象的引用关系,但是发现循环引用的时候,采用的是弱引用。

    image-20241015164654563

二、可达性分析法

2.1、介绍

可达性分析通过根对象(如全局变量、活动线程的局部变量等)来确定哪些对象是可达的。算法会标记所有可达的对象,然后清除未被标记的对象所占用的内存。

2.2、优缺点分析

2.2.1、优点
  • 处理循环引用:可达性分析可以有效地处理循环引用的问题,避免内存泄漏。

  • 不需要计数开销:不需要维护引用计数,减少了每次引用的开销。

2.2.2、缺点
  • 延迟回收:垃圾回收可能在某个特定的时刻发生,因此可能存在短期内无法释放内存的情况。

  • 实现复杂性:实现比引用计数法复杂,尤其是处理多线程和并发环境时。

  • 暂停应用程序:通常会暂停应用程序的执行以进行垃圾回收,可能导致用户体验不佳。

三、使用场景分析

这一部分,我将分析为什么Java中会使用可达性分析法,而在C/C++实现的一些嵌入式场景却要使用引用计数法。

我们知道引用计数法在对象不再使用时,引用计数会归零,并立即回收该对象的内存。因此,它非常适合实时性要求高的场景,因为内存的回收是即时的,能够快速释放不再使用的资源。然而,引用计数法也存在一个主要的局限——循环引用问题。当两个或多个对象相互引用时,即使它们已经不再被其他对象引用,引用计数也不会归零,导致内存无法被正确回收。为了解决这个问题,引用计数法通常需要额外的机制(例如周期性检查或手动触发的垃圾回收)来处理循环引用。

正是因为这个原因,引用计数法并不适用于像 Java 这种复杂的对象引用关系处理场景。Java 采用的是可达性分析来处理对象的回收,它更适合复杂的对象图结构,尤其是在存在循环引用的情况下,Java 的垃圾回收机制可以通过可达性分析检测出并回收这些对象,而不会依赖引用计数。

另一方面,对于嵌入式系统这种对垃圾回收实时性要求高,且内存资源有限的场景,引用计数法非常适用。嵌入式系统中的对象引用结构通常较为简单,不常出现循环引用问题。在这种场景中,程序的实时性能至关重要,而引用计数法能够帮助这些系统快速、即时地回收内存,以满足其实时性要求。因此,在嵌入式环境中,引用计数法的及时性和内存可预测性成为了其关键优势。

四、总结

在本文中,我们讨论了两种垃圾回收机制——引用计数法可达性分析法。引用计数法因其实时性简单性,适用于嵌入式等对回收延迟要求高的场景,但需要解决循环引用问题。而可达性分析法在处理复杂对象关系上更强,尤其适用于Java这类系统。同时选择哪种方法取决于应用的实时性、内存资源和引用结构。

所以,下次面试时,如果被问到这个问题,不要只提到可达性分析能解决循环引用问题。不妨通过对比引用计数法和可达性分析的优缺点,展示你对两者的深入思考,让面试官对你刮目相看吧。

最后的最后,觉得有收获?请为这篇文章点个赞,让我知道它帮助到了你!


http://www.kler.cn/a/349833.html

相关文章:

  • pytorch实现半监督学习
  • 网关登录校验
  • 危机13小时:追踪一场GitHub投毒事件
  • 嵌入式知识点总结 ARM体系与架构 专题提升(三)-中断与异常
  • ORA-04031 错误
  • 基于特征工程与转换方法的LightGBM资产预测研究
  • 静态路由、动态路由以及默认路由
  • 【计算机网络篇】数据链路层 协议、介质访问控制
  • 毕业32年,重回32中
  • 期刊论文投稿指南:如何利用ChatGPT精准选择合适的期刊?
  • Spring MVC实现高效文件上传及优化案例
  • 阿里巴巴1688上的图片批量保存下载的方法
  • Java面试宝典-并发编程学习01
  • 【数据结构与算法】力扣 42. 接雨水
  • mysql 10 单表访问方法
  • 物联网视频监控系统
  • 数据恢复与取证: 使用 OSForensics 从未启动 Android 设备中获取数据
  • [Gtk] layout.ui
  • php+mysql测试环境
  • 一、定时器的时钟来源
  • 面试知识梳理
  • 量化之一:均值回归策略
  • 4. 单例模式线程安全问题--是否加锁
  • 16 非类型安全:让你既爱又恨的 unsafe
  • 如何解决JMeter响应数据乱码?
  • AI测试入门:向量数据库 知识图谱的适用场景