返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

4.5.7 标准库函数

发布于 2024-10-12 19:15:59 字数 1800 浏览 0 评论 0 收藏 0

标准库里与调度相关的几个函数。了解实现细节,以便放心使用。

runtime.Gosched

让出当前 G 执行绪。与 gopark 的区别,G 会被放回队列,无需 goready 唤醒。

// proc.go

// Gosched yields the processor, allowing other goroutines to run. It does not
// suspend the current goroutine, so execution resumes automatically.
func Gosched() {
	mcall(gosched_m)
}

// Gosched continuation on g0.
func gosched_m(gp *g) {
	goschedImpl(gp)
}
func goschedImpl(gp *g) {
    
    // 修改状态。
	status := readgstatus(gp)
	if status&^_Gscan != _Grunning {
		dumpgstatus(gp)
		throw("bad g status")
	}
	casgstatus(gp, _Grunning, _Grunnable)
    
    // 解除 MP 绑定,放回全局队列。
	dropg()
	lock(&sched.lock)
	globrunqput(gp)
	unlock(&sched.lock)

    // 当前 MP 执行其他任务。
	schedule()
}

runtime.Goexit

终止当前任务。这与 return 返回调用堆栈上一级不同,而是直接结束整个任务。

在 Main Goroutine 调用 Goexit,它会等待其他 Gs 结束后才会崩溃。

注意,终止的是 G 函数执行,而不是 MP。

// panic.go

// Goexit terminates the goroutine that calls it. No other goroutine is affected.
// Goexit runs all deferred calls before terminating the goroutine. Because Goexit
// is not a panic, any recover calls in those deferred functions will return nil.
//
// Calling Goexit from the main goroutine terminates that goroutine
// without func main returning. Since func main has not returned,
// the program continues execution of other goroutines.
// If all other goroutines exit, the program crashes.

func Goexit() {
    
    // panic, defer ...
    
	goexit1()
}
// proc.go

// Finishes execution of the current goroutine.
func goexit1() {
	mcall(goexit0)
}

// goexit continuation on g0.
func goexit0(gp *g) {
	
    // G 任务结束,清理后放回复用链表。
    casgstatus(gp, _Grunning, _Gdead)
	dropg()
	gfput(_p_, gp)
    
    // 当前 MP 继续执行其他任务。
	schedule()
}

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

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

发布评论

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