go - 当更多工作人员被显式调用时,gomaxprocs 被忽略
问题描述
我如何使用 gomaxprocs?下面的代码设置了 gomaxprocs,但随后会产生更多的工人。我预计 2 个进程,但 5 个仍在运行。
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
func worker(i int, waiter chan struct{}, wg *sync.WaitGroup) {
defer func(waiter chan struct{}, wg *sync.WaitGroup) {
fmt.Printf("worker %d done\n", i)
wg.Done()
<-waiter
}(waiter, wg)
fmt.Printf("worker %d starting\n", i)
time.Sleep(time.Second)
}
func main() {
runtime.GOMAXPROCS(2)
var concurrency = 5
var items = 10
waiter := make(chan struct{}, concurrency)
var wg sync.WaitGroup
for i := 0; i < items; i++ {
wg.Add(1)
waiter <- struct{}{}
go worker(i, waiter, &wg)
}
wg.Wait()
}
解决方案
对于 C/C++ 程序员所认为的线程,Go 有三个概念:G、P、M。
- M = 实际螺纹
- G = Goroutines(即程序中的代码)
- P = 处理器
没有限制 Ms 数量的 Go API。没有限制 Gs 数量的 API - 每次go func(...)
调用都会创建一个新的。GOMAXPROCS
事情是为了限制Ps 。
每个 P 用于跟踪一些正在运行的Goroutine 的运行时状态。
您应该将其GOMAXPROCS
视为致力于运行Goroutines 的 Ms 的峰值数量。(还有其他 Ms 不运行 Goroutines,但处理垃圾收集任务并充当模板线程以根据需要创建新的 Ms 等。一些 Ms 致力于保持运行时状态,而一些 Go 代码在系统调用中被阻塞。)
因此,就您程序中的代码而言,GOMAXPROCS
它限制了其 Go 代码执行的并行程度。当一个正在运行的Goroutine到达它被阻塞的点时,它会被停住,并且它的 P 用于恢复执行其他一些未被阻塞的 Goroutine。
推荐阅读
- java - 由于 java.util.zip.ZipException,Tomcat 8 组件启动失败
- sql - 如何在选定的字符串中插入逗号?
- java - 如何在junit 5中为测试用例设置环境变量
- c - C 如何在进程之间共享信息?
- amazon-web-services - 在两个网站中使用存储桶 url 是否有任何限制?
- angular - 有没有办法等待在另一个 Observable 中调用的 Observable 的结果?
- css - 自定义清单列宽不起作用
- java - DynamoDB 等待表变为活动状态
- python - 修复散景放大和缩小的边界
- c++ - 在其命名空间之外定义的类成员函数