01 垃圾回收机制

01 垃圾回收机制

一、什么是垃圾回收机制?

  • 垃圾回收机制检测GC,是python解释器自带的一种机制,专门用来回收不可用得变量值所占用得内存空间

二、为什么要有垃圾回收机制?

  • 程序得运行过程中会申请大量的内存空间,而对于一些无用的内存空间如果不及时清理的话,会导致内存使用殆尽(也就是内存溢出),从而导致程序奔溃。因为管理内存是一件复杂且繁琐的事情,而python解释器自带的垃圾回收机制把程序员从复杂的内存管理中解放出来。

三、垃圾回收机制原理分析

1、什么是引用计数?

  • 运用了“引用计数”(reference counting)来跟踪和回收垃圾。
  • 引用计数就是变量值被变量名关联的次数。

1.1 直接引用

  • 通过变量名直接引用
x = 10  # 值10直接引用:1次
y = x   # 值10直接引用:2次
z = y   # 值10直接引用:3次
print(id(x))    # 140715024107456
print(id(y))    # 140715024107456
print(id(z))    # 140715024107456

1.2 间接引用

  • 主要争对容器类型
c = 10
li = ['a', 'b', c]  # 列表相当于['a', 'b', 10],值10被间接引用:1次
print(id(c))         # 140715024107456
print(id(li[-1]))   # 140715024107456, 值10被间接引用:2次


dic = {'key': c}        # 值10被间接引用:3次
print(id(dic['key']))   # 140715024107456, 值10被间接引用:4次

1.3 由引用关系刨析列表取值的底层原理过程

  • 我们知道列表是由所以取值,且列表能存多个任意类型的值,当我们通过列表取值时对应的正真的就是屏幕上我们所看到的值吗?我们来看图分析:

01 垃圾回收机制

  • 更具上图分析,列表的取值操作,我们是由索引对应值的内存地址,再通过这个内存地址找到对应值所在内存中的正真位置,列表当中相当于存放了内存地址的目录,通过这个目录我们访问到正真值所在的位置。

1.4 总结

  • 只要是访问到你那个值得方式,就相当于增加一次引用。
  • 只要是直接通过变量名访问值得方式,都是直接引用。
  • 间接引用一般是通过容器类型来进行对值得访问,例如:列表,字典类型等
  • 列表中的值并不是正真的值,而是通过内存地址映射到值得位置。

2、引用计数扩展阅读

2.1 标记清除

  • 通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用(也交交叉引用)的问题。
  • 循环引用时,值不再被任何名字关联,但是值的引用计数并不会为0,因该被回收,但不能被回收,这个时候就需要python的标记清除功能,清除没有被直接引用的值。
  • 标记清除程序并不是时时检测的,只有内存快满了,python程序才会启动标记清除程序,扫描栈区,如果谁身上没有直接引用的标识,它将根据对应内存地址去清除堆区的正真值占用的内存。
  • 栈区:存放变量名对应值得内存地址
  • 堆区:存放对应内存地址得值

01 垃圾回收机制

li1 = [10]
li2 = [20]
li1.append(li2)  # li1 = [值10对应得内存地址, 列表2对应得内存地址],此时列表li1得引用计数为2
li2.append(li1)  # li2 = [值20对应得内存地址,列表1对应额内存地址],此时列表li2得引用计数为2

del li1
del li2
# 通过del解除变量名li1与值[10]得绑定关系,变量名li2与值[20]的绑定关系,虽然解绑了直接引用,此时li1与li2得间接引用关系没有断,任然互相关联着,也就是说li1与li2值当前引用计数为1,但是它们并不能被访问到了,这就导致了它们一直占用了这块内存空间,这对于计算机来说是致命得。

# 总结:循环引用时,值不再被任何名字关联,但是值的引用计数并不会为0,因该被回收,但不能被回收。

总结

  • 标记清除是用来解决循环引用带来得内存泄漏问题。

2.2 分代回收

总结

  • 用来降低引用计数的扫描频率,提升垃圾回收的效率。
上一篇:QueryHelper插件类(hql)


下一篇:hive hql强化练习