GC_3_引用计数法


引用计数算法


3 引用计数法

  GC是一种,释放怎么都无法被引用的对象的机制。可以让所有对象事先记录下有多少程序引用自己,让各对象知道自己的人气指数,从而让没有人气的对象自己消失,这就是引用计数法(Reference Counting),由George E.Collins于1960年钻研出来的。

3.1 引用计数的算法

  引用计数算法中引入了计数器的概念,计数器表示的是对象的人气指数,也就是有多少程序引用了这个对象(被引用数)。下图是引用计数法中的对象。

  引用计数法中的对象

  在GC标记-清除算法等其他GC算法中,没有分块时mutator会启动GC分配空闲的内存空间。然而在引用计数法中并没有mutator明确启动GC的语句。引用计数法与mutator的执行密切相关,它在mutator的处理过程中通过增减计数器的值来进行内存管理。在以下两种情况下计数器的值会发生增减。

 1. 生成新对象
 2. 更新指针

  生成新对象:在引用计数法中,除了连接到空闲链表的对象,其他对象都是活动对象。也就是说,如果申请分块失败,则堆中就没有合适大小的分块,分配就无法进行了。如果找到了合适的分块,则把新生成对象的计数器的值定为1。很明显,这里新生成了对象,且对象被某处引用了。

  更新指针:mutator进行更新指针时会进行以下2项操作:

 1. 对指针新引用的对象的计数器进行增量操作
 2. 对指针之前引用的对象的计数器进行减量操作

  首先,对新引用的对象的计数器进行增量操作。然后,对更新指针之前引用的对象的计数器进行减量操作。减量操作后,计数器的值为0的对象就变成了垃圾。因此,这个对象的指针会全部被删除。换言之,就是要对垃圾对象的子对象的计数器进行减量操作。

  看到这里可能会产生疑问,为什么要先做增量操作然后再做减量操作?为了处理1和2操作的是同一对象,如果是同一对象的话,先执行减量操作则该对象的计数器的值就可能变为0而被回收。这样一来,想再对其进行增量操作时,对象早就已经被回收了。

  指针更新过程

  初始状态下从根引用A和C,从A引用B。A持有唯一指向B的指针,假设现在将该指针更新到了C。通过指针的更新,B的计数器变为0,因此B被回收了。且B连接上了空闲链表,能够再被利用了。又因为新形成了由A指向C的指针,所以C的计数器的值变为了2。

  在变更数组元素(替换数组中的某个对象)等的时候回进行指针的更新。通过更新指针,可能会产生没有被任何程序引用的垃圾对象。引用计数法中会监督在更新指针的时候是否产生垃圾,从而在产生垃圾时将其立刻回收。也就是说,这意味着在分配时没有分块的情况下,堆中所有的对象都为活动对象,这时没法新分配对象。另一方面,GC标记-清除算法即使产生了垃圾也不会将其马上回收,只会在没有分块的时候将垃圾一并回收。像这样,可以说将内存管理和mutator同时运行正是引用计数法的一大特征。

3.2 优点

3.2.1 可即刻回收垃圾

  在引用计数法中,每个对象是始终都知道自己的被引用数也就是计数器的值。当被引用数的值为0时,对象马上就会把自己作为空闲空间连接到空闲链表。也就是说,各个对象在变成垃圾的同时就会立刻被回收。这有什么意义呢,就是内存空间不会被垃圾占领。垃圾全部都已连接到空闲链表,能作为分块再被利用。

  另一方面,在其他的GC算法中,即使对象变成了垃圾,程序也无法立刻判别。只有当分块用尽后GC开始执行时,才能知道哪个对象是垃圾,哪个对象不是垃圾。也就是说,直到GC执行之前,都会有一部分内存空间被垃圾占用。

3.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值