前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang源码分析:runtime.SetFinalizer

golang源码分析:runtime.SetFinalizer

作者头像
golangLeetcode
发布2023-09-06 19:26:19
4990
发布2023-09-06 19:26:19
举报
文章被收录于专栏:golang算法架构leetcode技术php

当我们希望在对象被gc之前,做一些资源释放的工作,类似,函数返回之前执行defer操作一样,我们可以使用 runtime.SetFinalizer,它会在gc周期到来的时候,检查下对象有没有引用,如果没有引用,起一个协程,执行绑定的资源释放函数。执行完毕后解除绑定,当下一个gc周期到来的时候回收当前对象。

代码语言:javascript
复制
func SetFinalizer(obj any, finalizer any) {

的定义位于src/runtime/mfinal.go。详细信息可以看下它的注释,很完备。

通过分析具体注释我们可以总结出下面三点:

* 即使程序正常结束或者发生错误, 但是在对象被 gc 选中并被回收之前,SetFinalizer 都不会执行, 所以不要在SetFinalizer中执行将内存中的内容flush到磁盘这种操作。

* SetFinalizer 最大的问题是延长了对象生命周期。在第一次回收时执行 Finalizer 函数,且目标对象重新变成可达状态,直到第二次才真正 “销毁”。这对于有大量对象分配的高并发算法,可能会造成很大麻烦

* 指针构成的 "循环引⽤" 加上 runtime.SetFinalizer 会导致内存泄露

下面我们结合源码看下:

代码语言:javascript
复制
package main

import (
  "fmt"
  "runtime"
  "time"
)

func main() {
  // i 就是后面说的 数据对象
  var i = 3
  // 这里的func 就是后面一直说的 finalizer
  runtime.SetFinalizer(&i, func(i *int) {
    fmt.Println(i, *i, "set finalizer")
  })
  runtime.GC()
  time.Sleep(time.Second * 1)
  runtime.GC() //0xc000018168 3 set finalizer
  subFunc()
  time.Sleep(time.Second * 1)
  runtime.GC() //0xc000018180 3 set sub finalizer
}
func subFunc() {
  // i 就是后面说的 数据对象
  var i = 3
  // 这里的func 就是后面一直说的 finalizer
  runtime.SetFinalizer(&i, func(i *int) {
    fmt.Println(i, *i, "set sub finalizer")
  })
  runtime.GC()
}

我们强制gc后,由于没有引用,所以会执行finalize函数,但是下面的场景,由于存在相互引用,则会出现内存泄漏,不论我们强制多少次gc,都不会起作用。

代码语言:javascript
复制
package main

import (
  "fmt"
  "runtime"
)

func main() {
  memoryLeaking()
  runtime.GC()
  runtime.GC()
  runtime.GC()
}
func memoryLeaking() {
  type T struct {
    v [1 << 20]int
    t *T
  }

  var finalizer = func(t *T) {
    fmt.Println("finalizer called")
  }

  var x, y T

  // The SetFinalizer call makes x escape to heap.
  runtime.SetFinalizer(&x, finalizer)

  // The following line forms a cyclic reference
  // group with two members, x and y.
  // This causes x and y are not collectable.
  x.t, y.t = &y, &x // y also escapes to heap.
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档