https://github.com/golang/go/issues/60004

https://github.com/golang/go/commit/734b26d4b9b90cab4b770a8d55fdaeb3a7683bd7

排除额外的 M,它们用于 C 中创建的线程的 cgocallback。SetMaxThreads 限制的目的是避免意外的 fork 炸弹,例如数百万 goroutine 阻塞系统调用,导致运行时创建数百万个线程。 根据定义,这对于在 C 中创建的线程来说不是问题,因此我们将它们排除在限制之外。 请参阅 https:go.dev/issue/60004。 count := mcount() - int32(extraMInUse.Load()) - int32(extraMLength.Load()) 如果计数 > sched.maxmcount {

1
2
3
4
5
6
7
8
9
10
11
12
13
debug.SetMaxThreads的默认限制为10k个线程,这是在创建M时由runtime.checkmcount强制执行的。



https://go.dev/cl/485500为每个调用Go的C线程创建一个M,只有在线程退出时才释放M。因此,至少一次调用Go的10k个唯一C线程将触发线程耗尽抛出(假设线程没有退出)。在CL 485500之前,10k个线程都需要同时调用Go来触发抛出。



我认为我们完全不需要做任何事情。一个有10k个C线程的程序是例外的,我认为这样的程序应该调整debug.SetMaxThreads是合理的。



另一方面,这个限制的主要目的是防止Go程序意外地分叉轰炸系统。例如,通过创建100万个goroutine,所有goroutine都阻塞一个系统调用,从而需要100万个线程。这种担忧并不真正适用于C创建的线程,因为根据定义,我们并不是自动创建线程。因此,我认为从SetMaxThreads限制中排除额外的Ms是合理的。