golang cache 源码学习

本文探讨了Golang中缓存管理的关键点,通过C := &Cache{c}确保缓存对象不会被垃圾回收,同时利用runtime.SetFinalizer在C不可达时启动stopJanitor,停止维护过期缓存的goroutine,实现程序退出时的资源释放。
摘要由CSDN通过智能技术生成

github源码地址


func newCacheWithJanitor(de time.Duration, ci time.Duration, m map[string]*Item) *Cache {
    c := newCache(de, m)
    // This trick ensures that the janitor goroutine (which--granted it
    // was enabled--is running DeleteExpired on c forever) does not keep
    // the returned C object from being garbage collected. When it is
    // garbage collected, the finalizer stops the janitor goroutine, after
    // which c can be collected.
    C := &Cache{c}
    if ci > 0 {
        runJanitor(c, ci)
        runtime.SetFinalizer(C, stopJanitor)
    }
    return C
}

这段程序的关键点在于C := &Cache{c}* runtime.SetFinalizer(C, stopJanitor)*

首先,

func (j *janitor) Run(c *cache) {
    j.stop = make(chan bool)
    tick := time.Tick(j.Interval)
    for {
        select {
        case <-tick:
            c.DeleteExpired()
        case <-j.stop:
            return
        }
    }
}
func runJanitor(c *cache, ci time.Duration) {
    j := &janitor{
        Interval: ci,
    }
    c.janitor = j
    go j.Run(c)
}

可以看到runJanitor是启动了一个goroutine用于清除过期的缓存,这个goroutine是一直执行的,周期的检查c中有没有过期的缓存,所以c一直不会被垃圾回收。为了让程序停掉的时候该gorountine也能够停止,就需要利用C := &Cache{c}和runtime.SetFinalizer.

利用C := &Cache{c}, c虽然不会被垃圾回收,但是C会,那么当C被垃圾回收时,C变成unreachable 的状态,就会触发runtime.SetFinalizer,执行stopJanitor停止runJanitor启动的goroutine。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值