白色:待回收的对象
灰色:待遍历的对象
黑色:不回收的对象
主要流程:
1、从根集开始遍历
2、遍历到的白对象标灰入栈,遍历到灰色、黑色对象则跳过。
3、每次从栈中pop一个灰色对象标黑,并遍历它引用的对象(处理方式参考2)
4、直到栈为空,一次性将白色对象清理出内存。
流程特点:
第2、3步是可以分步进行的,但是要对新元素进行处理,避免遍历遗漏。
如何遍历table:
1、table要么没有被遍历到,整个被回收,要么其所有key、value最终是黑色,不会被回收
2、如果table的key、value都被设置了weak,那不用遍历了,这些key-value肯定要被回收,将table直接挂g->weak即可(table本身不回收)
如果table的key被设置了weak,这些key不需要遍历,肯定是要被回收,放白
如果table的value被设置了weak,这些value不需要遍历,和key同理
只要key被回收,整个key-value肯定是要从table中移除的,虽然不一定回收value。(value同理)
3、设置了weak的table需要标灰,但不再入栈。
为什么不标黑,因为这样可以防止被再次被置灰入栈吗?参考<往table插入新数据>
那么标黑会怎样?
1) 如果是往其他table插入这个table,这个table本来就是黑色的,原逻辑啥也不干。没问题!
2) 如果是往这个table添加元素,根据下面<往table插入新数据>,可能会被置灰入栈,
但这其实是没必要的,因为这个table已是weak,不用遍历其元素了。
4、元表metatable也会被遍历到
往table插入新数据:
1、若table是白色的,不用管它,有被引用最后肯定会被遍历到,没有的话回收也是应该
2、若table是灰色的,不用管它,反正一会就遍历到它,它的新数据也会遍历到
3、若table是黑色且新数据是白色,将table置灰入栈待重新遍历。(将新数据置灰入栈也行,省去重新遍历已经遍历过的元素)
闭包(函数)如何遍历:
函数里其实是有很多对象是引用到的,比如upvalue。
需要将这些引用到的所有upvalue都遍历一下。
字符串如何回收:
线程如何回收:
线程引用的对象都在栈里,遍历栈即可
其他类型如何回收:
两种白色是啥:
https://blog.codingnow.com/2011/03/lua_gc_1.html
|
请发表评论