1. 前言
Lua采用了自动内存管理,我们不需要删除对象,Lua会自动地删除那些已经成为垃圾的对象、
最重要的就是!当我们在纠结c++在回收时的环形引用问题时,Lua早就走在了前面,它没有环形引用问题,当要用到环形结构时,也能被正常回收。
垃圾回收器只会回收它认为是垃圾的东西,所以当我们使用栈的时候就会出现一个问题:我们以为我们不再使用的对象被回收了,但是其实它还没有被回收。原因如下:栈通常是由一个数组和一个表示顶部的索引来实现的,这个数组的的有效部分总是向顶部扩展,当我们弹出一个数据时,只是将顶部索引递减,而那个数据仍留在数组中,那么这对于Lua来说就不是垃圾。同理,那些全局变量,虽然不再使用了,但是仍然不是垃圾,需要用户手动将它们赋值为nil,Lua才会释放它们。
2. 弱引用table
当我们数组中引用了一个对象,那么这个对象就无法被回收。为了解决这个问题,Lua引入了弱引用table。
2.1 什么是弱引用
弱引用就是会被垃圾回收器忽视的对象引用,如果一个对象的引用都是弱引用,那么这个对象就可以被回收了
2.2 弱引用table的种类
正常情况下,table的key和value都是强引用的。
所以提出了三种弱引用table
- 具有弱引用key的table
- 具有弱引用value的table
- 同时具有两种弱引用的table
2.3 弱引用table的实现
它往往是通过元表中的__mode字段来决定的。
如果这个字段的值包含字母"k",是弱引用key
如果这个字段的值包含字母"v",是弱引用value
弱引用table的实现
Lua只会回收弱引用table中的对象,数字和布尔值以及字符串是不可回收的。
2.4 弱引用table在对象属性中的实现方式
当我们不想将对象属性存储在table中,想保持属性的私有性,我们可以将对象作为key,属性作为key的value,又因为key为对象,此时就会出现该对象无法回收的情况,所以这时候弱引用table有用处啦
3. 垃圾回收器
我先简述一下垃圾回收器的流程,后面的源码分析留到下一个博文再来讲
Lua的垃圾回收周期共分为四个阶段:标记、整理、清扫、收尾 。
在标记阶段,Lua会首先将根集合中的对象标记为活跃,然后将任何程序可以通过根节点访问到的对象也标记为活跃。
在整理阶段,Lua会遍历所有的userdata,找出未被标记且有gc元方法的userdata,将它们标记为活跃,并放入单独的列表中。再根据所有的弱引用table删除其未被标记的key和value。
在清扫阶段,Lua遍历所有对象,如果当前对象未被标记,就收集它,否则清除它的标记。
在收尾阶段,根据上面生成的userdata列表来调用终结函数
网友评论