博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家
感兴趣的同学可以收藏关注下 ,不然下次找不到哟
引用计数法(Reference Counting)是一种内存管理技术,用于跟踪对象的引用数量。在引用计数法中,每个对象都有一个引用计数器,记录着指向该对象的引用数量。当引用计数器为零时,表示没有任何引用指向该对象,该对象可以被释放,回收其占用的内存。
当一个对象被引用时,引用计数器加一;当一个引用被释放时,引用计数器减一。通过不断地增减引用计数器,系统可以动态地追踪对象的引用情况,并在适当的时候回收不再被引用的对象。
引用计数法的优点是实时性好,当没有引用指向一个对象时,该对象可以立即被回收,释放内存资源。然而,引用计数法也存在一些问题,比如循环引用的情况下,对象之间的引用计数可能永远不会为零,导致内存泄漏的发生。为了解决这个问题,通常需要引入其他的内存管理技术,如垃圾回收机制。
引用计数法的优点包括:
引用计数法的缺点包括:
延迟引用计数法的工作原理如下:
延迟引用计数法通过延迟释放对象,允许系统在一定时间内检测和解决循环引用问题,从而避免内存泄漏。这种方法的缺点是增加了内存管理的复杂性和延迟释放的开销,但相对于传统的引用计数法,它提供了更好的内存回收机制。
我们在延迟引用计数法中使用 ZCT(Zero Count Table)。ZCT 是一个表,它会事先记录下计数器值在 dec_ref_cnt() 函数的作用下变为 0 的对象。
因为计数器值为 0 的对象不一定都是垃圾,所以暂时先将这些对象保留。
在延迟引用计数法中用到的 dec_ref_cnt() 函数
dec_ref_cnt(obj){ obj.ref_cnt-- if(obj.ref_cnt == 0) if(is_full($zct) == TRUE) scan_zct() push($zct, obj)}
dec_ref_cnt() 函数会接收一个对象作为参数,然后将该对象的引用计数器减一。如果引用计数器减为零,说明没有任何引用指向该对象,可以释放对象所占用的内存资源。
用于记录引用计数。函数首先将 ref_count 减一,然后检查是否减为零。如果是,则调用 release_memory() 函数释放对象的内存。
延迟引用计数法的优点包括:
延迟引用计数法的缺点包括:
Sticky 引用计数法是一种内存管理技术,用于解决循环引用问题。它是引用计数法的一种变体,通过引入"sticky"标记来延迟释放对象。
在 Sticky 引用计数法中,除了常规的引用计数器外,还为每个对象引入一个"sticky"标记。当一个对象被引用时,它的引用计数会增加,并且"sticky"标记会被设置为真。当一个对象的引用计数减少到零时,它不会立即被释放,而是进入"sticky"状态。在这个状态下,对象的引用计数不再增加,但它的"sticky"标记仍然为真。
当对象处于"sticky"状态时,系统会定期进行垃圾回收。垃圾回收器会遍历所有的对象,并检查它们的引用计数和"sticky"标记。如果一个对象的引用计数为零且"sticky"标记为真,那么它可以被释放。
Sticky 引用计数法的优点是能够解决循环引用问题,避免内存泄漏。它相对于传统的引用计数法增加了"sticky"标记和垃圾回收的机制,但相比其他内存管理技术,它的实现相对简单。然而,它也存在一些缺点,如引入了额外的开销和延迟释放的性能损失。
Sticky 引用计数法可以通过以下两种方式来解决“爆表”(count overflow)的问题:
无符号整数扩展:在传统的引用计数法中,引用计数器通常使用有符号整数来表示引用计数。当引用计数增加到最大值时,继续增加会导致计数器溢出,变为负数。为了解决这个问题,可以将引用计数器改为无符号整数,这样当计数器达到最大值时,会从最小值重新开始,避免了溢出问题。
Big Counters:另一种解决方案是使用大型计数器。传统的引用计数法通常使用一个字节或几个字节来表示引用计数,这限制了计数器的最大值。为了解决这个问题,可以使用更大的计数器,比如使用64位整数来表示引用计数。这样可以大大增加计数器的最大值,减少计数器溢出的可能性。
1 位引用计数法是一种简单的引用计数算法,用于跟踪对象的引用数量。它使用一个单独的位来表示引用计数,只能存储0或1两个值。
在1位引用计数法中,每个对象都有一个与之关联的引用计数位。当一个对象被引用时,引用计数位被设置为1,表示有一个引用指向该对象。当引用被释放时,引用计数位被设置为0,表示没有引用指向该对象。
这种引用计数法的优点是简单、高效。由于只使用一个位来表示引用计数,它占用的内存非常小。而且,当引用计数位为0时,可以立即确定对象没有被引用,可以立即进行垃圾回收。
然而,1位引用计数法也有一些限制。由于只有一个位来表示引用计数,它只能跟踪两种状态(0或1),无法处理多个引用的情况。当多个引用指向同一个对象时,无法准确跟踪引用计数,可能导致引用计数的不准确和错误的内存管理。
1 位引用计数法的优点:
1 位引用计数法的缺点:
具体而言,1 位引用计数法可以解决以下问题:
然而,需要注意的是,1 位引用计数法无法解决循环引用的问题。当多个对象相互引用形成循环时,引用计数无法准确归零,可能导致内存泄漏。因此,在处理循环引用的情况下,需要使用其他的垃圾回收算法,如标记-清除算法或引用计数算法的改进版本。
在部分标记 - 清除算法中,对象会被涂成 4 种不同的颜色来进行管理。每个颜色的含义如下所示。
话虽这么说,事实上并没办法去给对象涂颜色,而是往头中分配 2 位空间,然后用 00~11 的值对应这 4 个颜色,以示区分。本书中用 obj.color 来表示对象 obj 的颜色。obj.color 取 BLACK、WHITE、GRAY、HATCH 中的任意一个值。
本文由激流原创,原创不易,感谢支持
喜欢的话记得点赞收藏啊
Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者