Goroutine在我设置了runtime.GOMAXPROCS(1)之后仍然可以工作。为什么呢?

huangapple go评论81阅读模式
英文:

Goroutine works even I set runtime.GOMAXPROCS(1). Why?

问题

这个简单的例子打印出了"done"和"finished"。在只有一个由runtime.GOMAXPROCS(1)限制的物理线程的情况下,这是如何可能的?Go 1.19

package main

import (
	"fmt"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(1)

	done := false

	go func() {
		done = true
		fmt.Println("done")
	}()

	for !done {
	}
	fmt.Println("finished")
}

这段代码的作用是将done设置为true,然后打印出"done"。在主线程中,通过循环等待done变为true,然后打印出"finished"。由于只有一个物理线程,循环会一直运行直到done变为true,然后才会打印出"finished"。

英文:

This simple example prints "done", "finished". How it's possible in case then we have only one physical thread limited by runtime.GOMAXPROCS(1)? Go 1.19

package main

import (
	"fmt"
	"runtime"
)

func main() {
	runtime.GOMAXPROCS(1)

	done := false

	go func() {
		done = true
		fmt.Println("done")
	}()

	for !done {
	}
	fmt.Println("finished")
}

答案1

得分: 3

GOMAXPROCS(1)不会将程序限制在单个线程上。它限制了可以同时执行用户级Go代码的操作系统线程的数量。对于代表Go代码进行系统调用的线程数量没有限制;

假设在这个上下文中调度器不被视为"用户级Go代码",那么它不会受到这个数字(1)的限制。

即使用户代码真的占用了所有可用的线程,用户代码仍然经常会被抢占以允许其他代码运行。有关更多详细信息,请参见preempt.go中的注释。


  1. 或许这里的"用户级"是指用户代码与内核代码之间的区别。在这种情况下,Go运行时调度器显然不是内核代码,但称其为"用户级Go代码"似乎是多余的。
英文:

GOMAXPROCS(1) does not limit the program to a single thread. What does it do?

> The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code;

Assuming that the scheduler is not considered "user-level Go code" in this context, it would not be constrained by this number (1).

Even if user code is really occupying all the available threads, user code can still often be preempted to allow other code to run. See the comment in preempt.go for more details.


  1. Maybe "user-level" here is meant in the sense of user code vs. kernel code. In that case, the Go runtime scheduler is obviously not kernel code, but it would seem to be redundant to call it "user-level Go code".

答案2

得分: 1

看到这么多负面评价真是令人惊讶。与此同时,没有人注意到Go调度器在14.1版本中行为变化的原因(https://go.dev/doc/go1.14):“goroutines现在是异步可抢占的”。这段代码在14.1版本之前应该会卡住,在后续版本中应该可以正常工作。

英文:

It's amazing to see so many negative ratings. At the same time, no one noticed that the reason for the change in the behavior of the go scheduler in 14.1 (https://go.dev/doc/go1.14 ) "goroutines are now asynchronously preemptible". This code should hang in versions up to 14.1 and work in later versions.

huangapple
  • 本文由 发表于 2022年8月11日 15:59:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/73317221.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定