🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 引用计数 ![](../../../../images/screenshot_1610865272023.png) - 每次引用一次 Person,就会在ref上加1(Stack上new Person(),HEAP的Array上引用了一次) ### 基于扫描的实现 - 维护一张引用表 - 每次扫描删除引用计数为0的节点 ![](../../../../images/screenshot_1610865622994.png) 全部删除需要扫描两次 第一次删除引用为0的,并减少引用次数, 第二次删除调整后引用为0的 ### 基于图的实现(常用) ![](../../../../images/screenshot_1610865805489.png) - "0"指向"1",标识"1"被"0"引用 - 圆圈外的为定点,圆圈中的为被引用次数 - 边有方向,就是有向图;边没有方向,就是无向图。 - 纵向表示被谁引用 - 横向表示引用了谁 In-degree 和 out-degree - 纵向标识 In-degree,横向标识 out-degree - 图中顶点1的 in-degree=2,也就是有两条边进入顶点1 - 图中顶点1的out- degree=0,也就是有0条边从顶项点1出去 - **In-degree=0代表可以马上回收** 用广度优先(BFS算法)进行图的表里 ``` queue.enqueue(start) visited ={start} while(queue size>0){ v= queue.dequeue visited.add(v) for u in outNodes(item){ if(!visited contains(u)){ queue enqueue(u) } } } ``` 如 "start" 从"0" 开始,因为"0"的引用计数为0 ,把零列出回收清单中,并且查看到0引用了"1","2",把引用计数减1,如果减去1后引用计数为0,则标识也可以进行回收, #### 一种解决环装引用的方案 - 增加一个检测环的程序(BFS) - 发现环,手动删除一条边 - 再次从引用计数为0的节点开始BFS回收内存 ![](../../../../images/screenshot_1610867542877.png) ## 问题 - 基于扫描的引用计数策略性能太慢→基于图的策略 - 每个对象需要多维护一个引用(ref) → 开销问题 - 如果Gc程序是另外的线程ref的维护会产生竞争条件,处理GC的时候 需要Stop- The-World