Golang Go语言中关于 goroutine 调度 GOMAXPROCS

发布于 1周前 作者 sinazl 来自 Go语言

Golang Go语言中关于 goroutine 调度 GOMAXPROCS

package main

import ( “runtime” “sync” )

func main() { runtime.GOMAXPROCS(1) var wg sync.WaitGroup wg.Add(20)

for i := 0; i < 10; i++ {
	go func(i int) {
		println(i)
		wg.Done()
	}(i)
}

for i := 10; i < 20; i++ {
	go func(i int) {
		println(i)
		wg.Done()
	}(i)
}
wg.Wait()

}

https://play.golang.org/p/nrEveScSaeI

问题: 执行结果为什么会先打印出 19 再顺序输出?请各位大佬不吝赐教

我记得之前有看过 M P G 模型中 GOMAXPROCS 可以控制 P 的数量


更多关于Golang Go语言中关于 goroutine 调度 GOMAXPROCS的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

13 回复

偶然而已,按什么顺序都是对的,goroutine 的执行顺序是不确定的

更多关于Golang Go语言中关于 goroutine 调度 GOMAXPROCS的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不是偶然 GOMAXPROCS设为 1 确实是顺序输出 只是最后一个先输出然后才开始顺序输出

不专业的回答:最后一个 goroutine 会被放在一个"即将被执行的"地方,优先级最高。
话说,goroutine 不需要关心顺序吧

没仔细了解过细节。设置 gomaxprocs 后,应该只是控制 p 的数量,没有控制 m 的数量吧? m 不变的话底层还是会有多个线程,一个 g 阻塞了,其他 m 会来偷 g 过去运行。不知道我理解的对不对。欢以上仅供参考,欢迎各位大佬赐教,确实没仔细了解过调度这一块

它会把最新的一个放到本地的 queue 中。这样它就会被优先执行

另外就算是单线程的协程也不能保证能顺序执行哇。主要看添加到队列里的形态,以及调度的情况

可是 m 执行需要 p 提供 context 吧

应该都在 local queue 里吧

你可以试下用 go run -race 跑,多跑几次,看看是不是偶然。

讨论这种未定义行为没有任何意义,开了竞态检测,顺序就可能不同。不同版本的调度器也有可能不同,不同的编译器实现的运行时也可能不同。所以这就是偶然的行为,你的程序是不可以依赖这种未定义行为的。

对,你说的没错。P 是为 m 提供一个上下文队列。不过除了一个 P 以外还有一个全局的 P,当 local P 满了以后,g 会移动到 global P 里面,由于 go 添加的队列时间不同说不定会导致 local 和 global 内的 g 顺序不一致呢。

确实 开了竞态检测 输出就会不同。感谢解答!!

在Golang(Go语言)中,goroutine 是其并发模型的核心,而 GOMAXPROCS 是一个环境变量或运行时函数,用于设置程序可以同时使用的逻辑处理器(OS线程)的数量。理解这两者之间的关系对于优化并发程序的性能至关重要。

goroutine 是一种轻量级的线程,由Go运行时管理。Go调度器负责在可用的逻辑处理器之间高效地调度这些 goroutine,以实现并发执行。

GOMAXPROCS 决定了Go运行时系统可以使用的最大逻辑处理器数量。默认情况下,它的值等于宿主机的CPU核心数。这意味着,如果你的机器有4个CPU核心,那么默认情况下 GOMAXPROCS 会被设置为4。

调整 GOMAXPROCS 可以影响 goroutine 的调度和并发程序的性能。如果设置的 GOMAXPROCS 值小于CPU核心数,那么即使有更多的核心可用,程序也无法充分利用它们。相反,如果设置的 GOMAXPROCS 值过高,可能会导致上下文切换过多,反而降低性能。

因此,在实际应用中,需要根据程序的特性和工作负载来合理设置 GOMAXPROCS。这通常涉及到对程序进行性能测试和分析,以确定最佳的 GOMAXPROCS 值。

总之,goroutineGOMAXPROCS 是Go语言中并发编程的关键要素。通过合理设置 GOMAXPROCS 并利用Go调度器的强大功能,可以构建出高效、可扩展的并发程序。

回到顶部