A common mistake is assuming that a goroutine yields only when it blocks. Since Go 1.14, a goroutine running for about 10 ms can be marked preemptible and context-switched, allowing a long-running job to share CPU time. section 8.2.1
Distinguish preemption from cooperative scheduling:
- Before Go 1.14, context switches occurred only in specific blocking cases such as channel operations, I/O, or mutex acquisition. section 8.2.1
- Since Go 1.14, the scheduler can interrupt a running goroutine and replace it with another runnable goroutine. section 8.2.1
- The scheduler also balances runnable work through local queues, the global queue, and work stealing. section 8.2.1
A long-running goroutine
A CPU-intensive merge-sort goroutine need not reach a channel operation or other blocking point before another goroutine receives CPU time; after roughly 10 ms, it can be preempted. section 8.2.1
Figure 8.6 An example of the current state of a Go application executed on a four-core machine. Goroutines that aren’t in an executing state are either runnable (pending being executed) or waiting (pending a blocking operation).
Use the runtime-state figure to distinguish executing, runnable, and waiting goroutines across multiple processor cores. section 8.2.1




