- 问题:以下测试代码验证 SetFinalizer 中,通过时间触发 GC 的情况下不生效
- 说明:
- 预期:触发 GC,由 GC 执行 Finalizer 方法
- 测试通过执行 `runtime.GC()` 方法手动触发 GC 符合预期
- 测试通过 `buf := make([]byte, 1024*1024*1024*10)` 触发 gcTriggerHeap 条件也能够符合预期
- 打开 `GODEBUG=gctrace=1`,通过 sleep 两次 120s(利用 gcTriggerTime 触发 GC),确实也看到 GC 触发的打印输出,但是却并没有执行注册好的 Finalizer 方法
```golang
package main
import (
"fmt"
"runtime"
"time"
)
type dog struct {
stop chan bool
}
func (d *dog) dog_run() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
fmt.Println("bark")
case <-d.stop:
fmt.Println("stop!!!!!!!!!")
return
}
}
}
type School struct {
Students []string
dog *dog
}
func dog_stop(s *School) {
s.dog.stop <- true
}
func (s *School) new() {
watch_dog := dog{
stop: make(chan bool, 1),
}
s.dog = &watch_dog
go watch_dog.dog_run()
}
func NewSchool(names ...string) *School {
school := School{Students: names}
school.new()
runtime.SetFinalizer(&school, dog_stop)
return &school
}
func main() {
school := NewSchool([]string{"pd"}...)
fmt.Println("start school", school)
time.Sleep(time.Second * 4)
school = nil
fmt.Println("closed school")
// 手动调用可以触发 Finalizer
// runtime.GC()
// 内存提升到阈值也是可以触发
// buf := make([]byte, 1024*1024*1024*10)
// buf[0] = 1
time.Sleep(time.Second * 60)
fmt.Println("wait 60")
time.Sleep(time.Second * 61) // 预期这里两分钟触发了 GC, 应该会调用dog_stop,为啥没有呢
fmt.Println("wait 60")
time.Sleep(time.Second * 60)
fmt.Println("wait 60")
time.Sleep(time.Second * 70)
fmt.Println("wait 70")
}
```
这是第二个 60s 触发 GC 时候的截图(也就是第一个 120s)
![image.png](https://static.studygolang.com/210623/72482e56d2d864abf488468aa360b0b1.png)
这是第四个 60s 触发 GC 时候的截图(也就是第2个 120s)
![image.png](https://static.studygolang.com/210623/5c907383d2409e04d0a16a162c70e688.png)