Lua教程(十三):弱引用table

 更新时间:2015年04月30日 09:15:32   投稿:junjie  
这篇文章主要介绍了Lua教程(十三):弱引用table,一个table的弱引用类型是通过其元表的__mode字段来决定的,如果该值为包含字符"k",那么table就是key弱引用,如果包含"v",则是value弱引用,如果两个字符均存在,就是key/value弱引用,需要的朋友可以参考下

Lua采用了基于垃圾收集的内存管理机制,因此对于程序员来说,在很多时候内存问题都将不再困扰他们。然而任何垃圾收集器都不是万能的,在有些特殊情况下,垃圾收集器是无法准确的判断是否应该将当前对象清理。这样就极有可能导致很多垃圾对象无法被释放。为了解决这一问题,就需要Lua的开发者予以一定程度上的配合。比如,当某个table对象被存放在容器中,而容器的外部不再有任何变量引用该对象,对于这样的对象,Lua的垃圾收集器是不会清理的,因为容器对象仍然引用着他。如果此时针对该容器的应用仅限于查找,而不是遍历的话,那么该对象将永远不会被用到。事实上,对于这样的对象我们是希望Lua的垃圾收集器可以将其清理掉的。见如下代码:

复制代码 代码如下:

a = {}
key = {}
a[key] = 1
key = {}
a[key] = 2
collectgarbage()
for k,v in pairs(a) do
    print(v)
end   
--输出1和2

在执行垃圾收集之后,table a中的两个key都无法被清理,但是对value等于1的key而言,如果后面的逻辑不会遍历table a的话,那么我们就可以认为该对象内存泄露了。在Lua中提供了一种被称为弱引用table的机制,可以提示垃圾收集器,如果某个对象,如上面代码中的第一个table key,只是被弱引用table引用,那么在执行垃圾收集时可以将其清理。

Lua中的弱引用表提供了3中弱引用模式,即key是弱引用、value是弱引用,以及key和value均是弱引用。不论是哪种类型的弱引用table,只要有一个key或value被回收,那么它们所在的整个条目都会从table中删除。

一个table的弱引用类型是通过其元表的__mode字段来决定的。如果该值为包含字符"k",那么table就是key弱引用,如果包含"v",则是value若引用,如果两个字符均存在,就是key/value弱引用。见如下代码:

复制代码 代码如下:

a = {}
b = {__mode = "k"}
setmetatable(a,b)
key = {}
a[key] = 1
key = {}
a[key] = 2
collectgarbage()
for k,v in pairs(a) do
    print(v)
end   
--仅仅输出2

在上面的代码示例中,第一个key在被存放到table a之后,就被第二个key的定义所覆盖,因此它的唯一引用来自key弱引用表。事实上,这种机制在Java中也同样存在,Java在1.5之后的版本中也提供了一组弱引用容器,其语义和Lua的弱引用table相似。

最后需要说明的是,Lua中的弱引用表只是作用于table类型的变量,对于其他类型的变量,如数值和字符串等,弱引用表并不起任何作用。

1. 备忘录(memoize)函数:

    用“空间换时间”是一种通用的程序运行效率优化手段,比如:对于一个普通的Server,它接受到的请求中包含Lua代码,每当其收到请求后都会调用Lua的loadstring函数来动态解析请求中的Lua代码,如果这种操作过于频率,就会导致Server的执行效率下降。要解决该问题,我们可以将每次解析的结果缓存到一个table中,下次如果接收到相同的Lua代码,就不需要调用loadstirng来动态解析了,而是直接从table中获取解析后的函数直接执行即可。这样在有大量重复Lua代码的情况下,可以极大的提高Server的执行效率。反之,如果有相当一部分的Lua代码只是出现一次,那么再使用这种机制,就将会导致大量的内存资源被占用而得不到有效的释放。在这种情况下,如果使用弱引用表,不仅可以在一定程度上提升程序的运行效率,内存资源也会得到有效的释放。见如下代码:

复制代码 代码如下:

local results = {}
setmetatable(results,{__mode = "v"}) --results表中的key是字符串形式的Lua代码
function mem_loadstring(s)
    local res = results[s]
    if res == nil then
        res = assert(loadstring(s))
        results[s] = res
    end
    return res
end

相关文章

  • Lua和C++语言的交互详解

    Lua和C++语言的交互详解

    这篇文章主要介绍了Lua和C++语言的交互详解,本文讲解了C++和Lua交互,涉及到获取Lua中普通变量的值,Lua中table的值和调用Lua中的函数,需要的朋友可以参考下
    2014-09-09
  • Lua中使用二维数组实例

    Lua中使用二维数组实例

    这篇文章主要介绍了Lua中使用二维数组实例,本文直接给出代码实例,看代码更容易理解,需要的朋友可以参考下
    2015-06-06
  • Lua中的变量类型与语句学习总结

    Lua中的变量类型与语句学习总结

    这篇文章主要介绍了Lua中的变量类型与语句学习总结,总结了Lua入门过程中的一些基础知识,需要的朋友可以参考下
    2016-06-06
  • Luvit像Node.js一样写Lua应用

    Luvit像Node.js一样写Lua应用

    今天小编就为大家分享一篇关于Luvit像Node.js一样写Lua应用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Lua中写排序算法实例(选择排序算法)

    Lua中写排序算法实例(选择排序算法)

    这篇文章主要介绍了Lua中写排序算法实例,本文用一个选择排序算法为例讲解如何在Lua中写一个排序算法,需要的朋友可以参考下
    2015-04-04
  • 在Lua程序中使用SQLite的教程

    在Lua程序中使用SQLite的教程

    这篇文章主要介绍了在Lua程序中使用SQLite的教程,包括建立连接到基本的查询等一些操作,需要的朋友可以参考下
    2015-05-05
  • Lua脚本实现递归删除一个文件夹

    Lua脚本实现递归删除一个文件夹

    这篇文章主要介绍了Lua脚本实现递归删除一个文件夹,本文给出了C++和Lua两个版本的实现代码,需要的朋友可以参考下
    2015-05-05
  • 使用Lua编写Web端模板引擎的实例代码分享

    使用Lua编写Web端模板引擎的实例代码分享

    这里我们给出一个使用Lua编写Web端模板引擎的实例代码分享,力求简洁(核心代码约为70行),仅实现最基本的模板功能:
    2016-06-06
  • Lua 数学库的所有函数功能作用一览

    Lua 数学库的所有函数功能作用一览

    这篇文章主要介绍了Lua 数学库的所有函数功能作用一览,本文罗列了lua数学库的所有函数,并对每个函数的功能作用做了简短描述,需要的朋友可以参考下
    2015-06-06
  • Lua中的基本语法、控制语句总结

    Lua中的基本语法、控制语句总结

    这篇文章主要介绍了Lua中的基本语法、控制语句总结,本文总结了赋值、局部变量与块、控制结构、数字型for、泛型for等内容,需要的朋友可以参考下
    2014-09-09

最新评论