美文网首页
lua-弱表

lua-弱表

作者: Teech | 来源:发表于2019-04-28 14:48 被阅读0次

    弱表是是具有弱引用的表,如果只有弱引用,垃圾收集器会回收这些对象。弱表可以有弱键或者弱值,如果具有弱键,垃圾回收器会回收键不会回收值,反之亦然。弱表通过他的元表的__mode字段来控制到底属于弱键,弱值。

    local mt = {__mode = "k"} --弱键
    local weakTable = {}    
    --weakTable为弱表
    setmetatable(weakTable,mt)
    
    local key1 = {} --new一个空table1
    local key2 = {} --new一个空table2
    
    function printTb(tb)
        print("--------------------------")
        for k,v in pairs(weakTable) do
            print("key ",k,"value ",v)
        end 
    end
    
    weakTable[key1] = 1 
    weakTable[key2] = 2 
    printTb(weakTable)
    
     --把局部变量key1对table1引用解除
    key1 = nil     
    
    --开始完整的gc,目前对table1的引用,只有weakTable
    --因为weakTable为弱键的表,所以垃圾回收器会回收table1,
    --table2因为还有个局部变量key2对其引用,所以垃圾回收器不会回收
    collectgarbage()
    printTb(weakTable)
    
    --[[
    最终打印结果 可以观察到table1会回收。
    --------------------------
    key     table: 0x16819a0    value   1
    key     table: 0x1681ed0    value   2
    --------------------------
    key     table: 0x1681ed0    value   2
    ]]
    

    上面是一个弱键的例子,在看一个弱值的例子

    local mt = {__mode = "v"} --弱键
    local weakTable = {}    
    --weakTable为弱表
    setmetatable(weakTable,mt)
    
    local value1 = {} --new一个空table1
    local value2 = {}   --new一个空table2
    
    function printTb(tb)
        print("--------------------------")
        for k,v in pairs(weakTable) do
            print("key ",k,"value ",v)
        end 
    end
    
    weakTable[1] = value1
    weakTable[2] = value2
    printTb(weakTable)
    
    value1 = nil        --把局部变量value1对table1引用解除
    --开始完整的gc,目前对table1的引用,只有weakTable
    --因为weakTable为弱值的表,所以垃圾回收器会回收table1,
    --table2因为还有个局部变量value2对其引用,所以垃圾回收器不会回收
    collectgarbage()
    printTb(weakTable)
    --[[
    最终打印结果 可以观察到table1会回收。
    --------------------------
    key     1   value   table: 0x142e9a0
    key     2   value   table: 0x142eed0
    --------------------------
    key     2   value   table: 0x142eed0
    ]]
    

    “强值弱键”的弱表被称为ephemeron表,在表中,只有键可以被访问到才可以认为值可以被访问到,当只有键可以访问到值的时候,键值对会被移出(因为垃圾收集器回收了键)。如果把表模式从弱模式修改成普通模式在下一轮收集周期生效,所以本轮收集周期会回收部分。
    弱表中只有explicit construction才会从弱表移出,比如值:numbers,和light c函数就不会收集。尽管字符串会被提交到垃圾收集器,但是因为没有explicit construction,所以字符串也不回从弱表移除。

    local mt = {__mode = "v"} --弱键
    local weakTable = {}    
    --weakTable为弱表
    setmetatable(weakTable,mt)
    
    local a = 100  
    local b = 101  
    local value1 = a
    local value2 = b
    function printTb(tb)
        print("--------------------------")
        for k,v in pairs(weakTable) do
            print("key ",k,"value ",v)
        end 
    end
    
    weakTable[1] = value1
    weakTable[2] = value2
    printTb(weakTable)
    
    value1 = nil  
    collectgarbage()
    printTb(weakTable)
    --[[最终打印结果
    --------------------------
    key     1   value   100
    key     2   value   101
    --------------------------
    key     1   value   100
    key     2   value   101
    ]]
    查看部分反编译指令信息
    ; (06)  local a = 100   
    004B  81C00000           [08] loadk      2   3        ; 100
    ; (07)  local b = 101
    004F  C1000100           [09] loadk      3   4        ; 101
    ; (08)  local value1 = a 
    0053  00010001           [10] move       4   2      
    ; (09)  local value2 = b
    0057  40018001           [11] move       5   3    
    ; (18)  weakTable[1] = value1
    0067  49000183           [15] settable   1   262 4    ; 1
    ; (19)  weakTable[2] = value2
    006B  49408183           [16] settable   1   263 5    ; 2
    
    a,b分别在栈上,然后把常量表中的值move进a,b。
    value1,value1也是move操作。值直接拷贝,不是指针的引用,所以number类型的值这里是不会被垃圾收集器回收掉。
    

    弱表的应用,看到大部分的应用都是作为cache或者说记忆函数来使用,不用负责手动解引用释放表中pairs,会自动被gc。如果外部有对value的引用,那么gc的时候不会释放。

    function makeCache()
        return setmetatable({},{__mode = "kv"})
    end
    local cache = makeCache()
    
    function getValue(key)
        if cache[key] then
            return cache[key] 
        else
            cache[key] = loadstring("test")
            return cache[key] 
        end
    end
    

    相关文章

      网友评论

          本文标题:lua-弱表

          本文链接:https://www.haomeiwen.com/subject/ysydnqtx.html