引用计数器为主,标记清除和分代回收为辅+缓存机制
- 对象的引用计数机制垃圾回收机制内存池机制
引用计数器
当创建一个对象时,比如name='lkx', # 创建的任何对象都会加到这个双向链表中 python底层会创建一个环状的双向链表refchain,分别存储 上一个对象、 下一个对象、 类型(int、float、str)、 引用个数、 值. 如果创建的是(有多个元素组成的对象)列表元组字典集合,还会存储列表长度。
data = 3.14
内部会创建:
_ob_next = refchain中的上一个对象
_ob_prev = refchain中的下一个对象
ob-refcnt = 1 (引用计数,默认是1)
ob_type = float
ob_fval = 3.14
name = 'lkx'
new_name = name # new_name 指向name
此时name的引用个数 +1
del new_name new_name 变量删除,对应的对象引用计数器-1
del name name 变量删除,对应的对象引用计数器-1
# 此时name就会从双向链表中清除
当一个对象引用计数器为0时,意味着没人使用了,这个对象就是垃圾,回收。
1. 对象从refchain链表移除
2. 将对象销毁,内存归还给系统
标记清除
循环引用
# 如果仅使用引用计数器,会有一个bug v1 = [1,2,3] v1 引用计数器 =1 v2 = [4,5,6] v1 引用计数器 =1 v1.appendd(v2) v2 引用计数器 +1 v2.appendd(v1) v1 引用计数器 +1 del v1 v1 引用计数器 -1 del v2 v2 引用计数器 -1 # 但是此时并不为0 这种代码过多时,内存一直被消耗
为了解决引用计数器循环引用的不足
# 在python底层再维护一个链表,专门放可能循环引用的对象(元素里面可以再放其他元素) 比如列表元组集合字典分代回收
# 把可能存在循环引用的对象维护成3个链表(每一代都是双向链表) 0代:个数达到700,则扫描一次 1代:0代扫描10次,则1代扫描1次 2代:1代扫描10次,则2代扫描1次



