package main
import (
"fmt"
"runtime"
"time"
)
type Garbage struct
{
a int
}
func notify(f *Garbage) {
stats := &runtime.MemStats{}
runtime.ReadMemStats(stats) //go 标准库ReadMemStats将内存申请和分配的统计信息填写进f
fmt.Println("Last GC was:", stats.LastGC) //go 标准库uint64 // 上次运行的绝对时间(纳秒)
go ProduceFinalizedGarbage()
}
func ProduceFinalizedGarbage() {
x := &Garbage{}
runtime.SetFinalizer(x, notify)
// GO 标准库
//SetFinalizer将x的终止器设置为f。当垃圾收集器发现一个不能接触的(即引用计数为零,程序中不能再直接或间接访问该对象)具有终止器的块时,它会清理该关联(对象到终止器)并在独立go程调用f(x)。这使x再次可以接触,但没有了绑定的终止器。如果SetFinalizer没有被再次调用,下一次垃圾收集器将视x为不可接触的,并释放x。
//SetFinalizer(x, nil)会清理任何绑定到x的终止器。
//参数x必须是一个指向通过new申请的对象的指针,或者通过对复合字面值取址得到的指针。参数f必须是一个函数,它接受单个可以直接用x类型值赋值的参数,也可以有任意个被忽略的返回值。如果这两条任一条不被满足,本函数就会中断程序。
//终止器会按依赖顺序执行:如果A指向B,两者都有终止器,且它们无法从其它方面接触,只有A的终止器执行;A被释放后,B的终止器就可以执行。如果一个循环结构包含一个具有终止器的块,该循环不能保证会被当垃圾收集,终止器也不能保证会执行;因为没有尊重依赖关系的顺序。
//x的终止器会在x变为不可接触之后的任意时间被调度执行。不保证终止器会在程序退出前执行,因此一般终止器只用于在长期运行的程序中释放关联到某对象的非内存资源。例如,当一个程序丢弃一个os.File对象时没有调用其Close方法,该os.File对象可以使用终止器去关闭对应的操作系统文件描述符。但依靠终止器去刷新内存中的I/O缓冲如bufio.Writer是错误的,因为缓冲不会在程序退出时被刷新。
//如果*x的大小为0字节,不保证终止器会执行。
//一个程序会有单独一个go程顺序执行所有的终止器。如果一个终止器必须运行较长时间,它应该在内部另开go程执行该任务。
}
func main() {
go ProduceFinalizedGarbage()
for {
runtime.GC() // GC执行一次垃圾回收Go 标准库
//扫描队列4
//从根对象开始扫描从⼀开始⼤家都是⽩的,如果根对象有引⽤,那个对象变成灰⾊的,灰⾊对象依次扫描以后就剩下变成两种对象,⽩⾊对象和灰⾊对象,⽩⾊对象先放在这,灰⾊对象放⼊队列⾥⾯去,接下来我们从队列⾥把灰⾊对象取出来,看看灰⾊对象引⽤了什么对象,
// 灰⾊对象本⾝变成⿊⾊的它肯定活下来的,因为它是被别⼈引⽤了才会放⼊队列⾥⾯,
// 所以它从灰⾊变成⿊⾊肯定是活下来的。通过这样把灰⾊对象⼀级⼀级进⾏递归扫描以后最后这个队列被清空了,剩下来的世界只有两种对象,⼀种是⿊⾊的肯定被引⽤过,第⼆种是没有被引⽤过的⽩⾊对象,⿊⽩两⾊,⿊⾊活着⽩⾊干掉,这就是很典型的三⾊标记
//
//STM
//在扫描之前执⾏ STW(Stop The World)操作,就是Runtime把所有的线程全部冻结掉,所有的线程全部冻结掉意味着⽤户逻辑肯定都是暂停的,
// 所有的⽤户对象都不会被修改了,这时候去扫描肯定是安全的,对象要么活着要么死着,所以会造成在 STW 操作时所有的线程全部暂停,⽤户逻辑全部停掉,
// 中间暂停时间可能会很⻓,⽤户逻辑对于⽤户的反应就中⽌了。
time.Sleep(30 * time.Second) // Give GC time to run
}
}
运行结果:
Last GC was: 1545181742411382500
Last GC was: 1545181802413919800
Last GC was: 1545181862414543200
Last GC was: 1545181922416325800
Last GC was: 1545181982418128300
Last GC was: 1545182042418343900
Last GC was: 1545182102419360000
Last GC was: 1545182162420859800
Last GC was: 1545182222421522400
Last GC was: 1545182282422021600
Last GC was: 1545182342422330800
over..
Thank you
有疑问加站长微信联系(非本文作者))