刚刚学习了golang GMP模型,现在我了解了goroutines、操作系统线程和golang上下文/处理器如何相互协作。但我还是不明白什么时候会产生M和P?
例如,我有一个测试代码来在数据库上运行一些操作,并且有两个测试用例(两批 goroutine):
func Test_GMP(t *testing.T) {
for _ = range []struct {
name string
}{
{"first batch"},
{"second batch"},
} {
goroutineSize := 50
done := make(chan error, goroutineSize)
for i := 0; i < goroutineSize; i++ {
go func() {
// do some databases operations...
// each goroutine should be blocked here for some time...
// propogate the result
done <- nil
}()
}
for i := 0; i < goroutineSize; i++ {
select {
case err := <-done:
assert.NoError(t, err)
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for txFunc goroutine")
}
}
close(done)
}
}
以我的理解,如果M是在需要时创建的。在第一批 goroutine 中,将创建 8 个(我计算机上的虚拟核心数量)操作系统线程,第二批将仅重用这 8 个操作系统线程,而不创建新线程。这是正确的吗?
如果您可以提供有关此主题的更多材料或博客,我们将不胜感激。
正确答案
仅当您的进程没有阻塞或没有任何系统调用时,M 才可重用。在您的情况下,您的 go func()
中有阻塞任务。因此,M 的数量不会限制为 8(我计算机上的虚拟核心数)。第一批将阻塞并从 P 中删除,并等待阻塞进程完成,同时新的 M 创建与 P 的关联。
请参阅以下内容了解更多详细信息,
- https://www.php.cn/link/a4a1108bbcc329a70efa93d7bf060914
- go-goroutine-操作系统线程和CPU管理