主要是利用“引用计数”(reference counting)来跟踪和回收垃圾,在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环利用的问题,并且通过”分代回收“(generation collection)以空间换取时间的方式进一步提高垃圾回收的效率
- 引用计数:变量值与变量名关联的次数,变量值的引用计数为0的时候,其占用的内存地址就会被回收
计数+
对象创建、对象被引用、对象被作为参数,传到函数中、对象被作为元素,存储在容器中
计数-
对象的别名被显式销毁、对象的引别名被赋予新的对象、一个对象离开它的作用域、将元素从容器中删除或者容器被销毁时
- 标记清除
内存中有两块区域:栈区和堆区,在定义变量时,变量名存放于栈区,变量值存放于堆区,内存管理回收的时堆区的内容。
标记的过程,就是遍历所有的GC Roots(栈区中的所有内容和线程),然后将所有GC Roots对象可以直接或间接访问到的对象标记为存活的对象。
清除的过程就是遍历堆中的所有对象,将没有标记的对象全部清除掉。
- 分代回收分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,对象的存活时间长,它们的垃圾收集频率就小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。
