Search code examples
multithreadinggoschedulergoroutinepreemption

Why is Go considered partially preemptive?


I am trying to get a better understanding of the definition preemptive and cooperative in the context of Go. Wiki states for preemptive multitasking

In computing, preemption is the act of temporarily interrupting an executing task, with the intention of resuming it at a later time. This interrupt is done by an external scheduler with no assistance or cooperation from the task.

Wiki states "external scheduler". I guess it means dispatcher to be more specific since afaik the scheduler only is responsible for choosing the next process in line.

Go is often referred to as partially preemptive since sync-points/preemption-points are only at function calls and not at any given instruction. That makes sense. But as the wiki definition states, preemptive is done by an external scheduler.

But isn't every process or task preemptive since the CPU can stop executing any process mid-execution in order to switch to another process? Any clarification is appreciated!

Addendum

The only explanation I could come up with is that we talk about different preemption levels. One for processes, and one for kernel/user-threads. In that case the CPU scheduler selects the next process but the Go scheduler is responsible for the goroutines/threads.


Solution

  • Your addendum is correct. There are different schedulers working here. One is the OS scheduler and one on the application level. Check out this article. It's exactly what you are looking for:

    As we discussed in the first post, the OS scheduler is a preemptive scheduler. [...] The kernel is making decisions and everything is non-deterministic.

    And this:

    The Go scheduler is part of the Go runtime, and the Go runtime is built into your application. This means the Go scheduler runs in user space, above the kernel. The current implementation of the Go scheduler is not a preemptive scheduler but a cooperating scheduler. Being a cooperating scheduler means the scheduler needs well-defined user space events that happen at safe points in the code to make scheduling decisions.

    Conlusion, there are two different schedulers. One for the process, one for Goroutines.