Goroutine Yield Points Beyond System Calls
In Go programs, goroutines are the primary mechanism for concurrency. While syscalls that would block a goroutine are known yield points, the understanding of goroutine scheduling is not complete without considering other possible yield points.
One suspected yield point is function calls, as they require the scheduler to check for stack growth. However, it has been stated that "a goroutine will lock the thread until it exits or hits something that could yield execution to others" if it only performs mathematical operations.
To test this, a program was created that runs three loops (one in the main function and two in separate goroutines) without any function calls. The program sets GOMAXPROCS to 1, limiting the number of OS threads that can execute Go code concurrently. However, the output still shows interleaved messages from the main function and goroutines, suggesting that goroutines do yield control even without function calls.
The answer to this apparent discrepancy lies in asynchronous preemption introduced in Go 1.14, which adds potential preemption points almost everywhere. Therefore, goroutines can yield control at various points other than blocking syscalls.
While the exact implementation of preemption points may change between Go releases, asynchronous preemption ensures that loops without function calls no longer deadlock the scheduler or significantly delay garbage collection. Nonetheless, it's important to note that unsynchronized array writes and non-atomic index updates can introduce cooperative scheduling points that may impact program behavior.
The above is the detailed content of Do Goroutines Yield Control Beyond System Calls and Function Calls?. For more information, please follow other related articles on the PHP Chinese website!