返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

7.3 执行

发布于 2024-10-12 19:16:08 字数 2038 浏览 0 评论 0 收藏 0

创建专门的 goroutine 用于执行终结函数。

在 SetFinalizer 中被调用。

// mfinal.go

func createfing() {
    // start the finalizer goroutine exactly once
    if fingCreate == 0 && atomic.Cas(&fingCreate, 0, 1) {
        go runfinq()
    }
}

两个全局标记,分别代表唤醒和休眠。

var fingwait bool
var fingwake bool

var fing *g         // goroutine that runs finalizers
// mfinal.go

// This is the goroutine that runs all of the finalizers

func runfinq() {

    for {
        
        // 直接取下整个待运行队列,避免并发干扰。
        fb := finq
        finq = nil
        
        // 队列空,休眠。
        // 以后由 findrunnable 调用 wakefing 唤醒。
        if fb == nil {
            gp := getg()
            fing = gp            // 保存当前 G。
            fingwait = true      // 设置休眠标记。
            
            goparkunlock(&finlock, waitReasonFinalizerWait, traceEvGoBlock, 1)
            continue
        }
        
        // 遍历执行队列。
        for fb != nil {
            
            // 遍历单个 finblock 内终结器数组。
            for i := fb.cnt; i > 0; i-- {
                f := &fb.fin[i-1]
                
                // 执行。
                fingRunning = true
                reflectcall(nil, unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz))
                fingRunning = false
                
                atomic.Store(&fb.cnt, i-1)
            }
            
            // 调整队列,遍历下个块。
            // 当前块(fb)放回缓存(finc)头部。
            next := fb.next
            fb.next = finc
            finc = fb
            fb = next
        }
    }
}

唤醒条件:已休眠,外加队列有内容(queuefinalizer)。

// proc.go

func findrunnable() (gp *g, inheritTime bool) {
    if fingwait && fingwake {
        if gp := wakefing(); gp != nil {
            ready(gp, 0, true)
        }
    }
}
// mfinal.go

func wakefing() *g {
    var res *g
    
    if fingwait && fingwake {
        fingwait = false
        fingwake = false
        res = fing
    }
    
    return res
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文