Preemption
- Go course
- Expert
- Lesson 4/34
- 4 min
Learn how the Go scheduler forcibly suspends goroutines.
Preemption
If a goroutine holds a P too long, others starve. Since Go 1.14 the scheduler uses asynchronous preemption: a monitor called sysmon sends a signal to the thread of a goroutine running longer than 10 ms and stops it at a safe point.
go func() {
for {} // before Go 1.14 this could hold the P forever
}()Previously preemption could only happen at function calls; tight loops could freeze the whole program.
Cooperative points
Besides preemption, goroutines also release the P on their own: channel operations, locks, time.Sleep, network I/O and runtime.Gosched(). The stack-growth check at every function entry also acts as a preemption point. That's why in real programs goroutines change hands often.
Practice Running beside a tight loop
Set runtime.GOMAXPROCS(1). Start an infinite for {} loop in a goroutine. Then call time.Sleep(20 * time.Millisecond) and print fmt.Println("main devam etti"). Thanks to preemption the program doesn't freeze.
Starter code
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// buraya yaz
}Sample solution
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(1)
go func() {
for {
}
}()
time.Sleep(20 * time.Millisecond)
fmt.Println("main devam etti")
}Expected output
main devam etti
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What mechanism triggers asynchronous preemption?
- The GC finishing
- A channel closing
- A signal sent to the thread by sysmon Correct answer
- The stack check in a function call
Explanation: On Unix SIGURG is used; the signal handler saves the goroutine's context and returns to the scheduler.
2 Time threshold
const forcePreemptNS = ____ * 1000 * 1000
const forcePreemptNS = 10 * 1000 * 1000
Explanation: The Go scheduler's time slice is about 10 ms.
3 Way to yield
| Term | Meaning |
|---|---|
Waiting on a channel |
Cooperative |
runtime.Gosched |
Voluntary yield |
Sinyal (SIGURG) |
Async preemption |
Function entry |
Stack-check point |