3、python垃圾回收机制
什么是垃圾回收机制
python解释器自带的一种用来回收不可用的变量值所占用的内存空间的方式
为什么需要垃圾回收机制
不可访问的内存地址对于程序来说没有意义了,回收掉可以节省内存空间
引用计数
引用计数就是变量值被变量名关联的次数
age = 18 # 引用计数为1 m = age # 引用计数为2 del age # 引用计数减为1 del m # 引用计数为0, 18占用的内存空间被回收
单纯采用引用计数机制并不能及时地回收掉内存垃圾,比如,下面这种循环引用就会引起一些问题
l1 = ['xxx'] # 列表1的引用计数为1 l2 = ['yyy'] # 列表2的引用计数为1 l1.append(l2) # 列表2的引用计数为2 l2.append(l1) # 列表1的引用计数为2 print(l1) # ['xxx', ['yyy', [...]]] print(l2) # ['yyy', ['xxx', [...]]] del l1 # 列表1的引用计数减为1 del l2 # 列表2的引用计数减为1
那么问题来了,这样一来,不能通过变量名l1和l2访问到对应的列表了,但是单单按照引用计数的规则,l1和l2互相引用,它们的引用计数又都不为0,所以都不会被视为垃圾,那么岂不是有一块内存空间被浪费了?还好,python引入了“标记-清除” 与“分代回收”来分别解决引用计数的循环引用与效率低的问题
标记-清除
标记-清除,就是为了解决循环引用而发明的。
标记:从内存的栈区出发,能连接一条线到达堆区,凡是被这条线连接到的内存空间都是可以访问的,会标记为存活
清除:遍历堆区中的所有对象,将没有标记为存活的对象全部清除掉
当删除变量名时,相当于删除了堆区和栈区之间的连线,这样就会把两个变量标记为不存活,理所应当被回收
分代回收
基于引用计数的回收机制,每次回收内存,都需要把所有对象的引用计数都遍历一遍,这是非常消耗时间的,于是引入了分代回收来提高回收效率,分代回收采用的是用“空间换时间”的策略。
分代回收的核心思想是:在历经多次扫描的情况下,都没有被回收的变量,垃圾回收机制就会认为这个变量是经常使用的变量,会降低对它的扫描频率