Here is an example of Windows that will probably help you understand what is going on. It prints the identifiers of the threads running goroutines. I had to use syscall, so it only works on Windows. But you can easily transfer it to other systems.
package main import ( "fmt" "runtime" "golang.org/x/sys/windows" ) func main() { runtime.GOMAXPROCS(1) runtime.LockOSThread() ch := make(chan bool, 0) go func(){ fmt.Println("2", windows.GetCurrentThreadId()) <- ch }() fmt.Println("1", windows.GetCurrentThreadId()) <- ch }
I do not use sleep to prevent runtime from spawning another thread to mate goroutine. The channel will block and simply remove goroutine from the execution queue. If you execute the code, you will see that the thread IDs are different. The main goroutine blocked one of the threads, so the runtime should spawn another one.
As you already know, GOMAXPROCS does not prevent runtime from creating new threads. GOMAXPROCS is more about the number of threads that goroutines can execute in parallel. But more threads can be created for goroutines, which wait for syscall to complete, for example.
If you delete runtime.LockOSThread() , you will see that the thread IDs are equal. This is because reading a channel blocks goroutine and allows execution to execute execution on another goroutine without creating a new thread. That several gorut can be executed at the same time, even when GOMAXPROCS is 1.
creker
source share