Context switching moves CPU execution from one job or thread to another. The current execution state is saved, the next state is loaded, and the interrupted work can later resume. On a single CPU, repeated switches make multiple tasks appear to run at once; on multiple CPUs, tasks may also run truly in parallel. section 2.1 section 2.4
The saved state is the process context block (PCB), which holds details needed to resume work, including the program counter, CPU registers, and memory information. Saving and restoring that state adds overhead to every switch, so switching enables responsiveness but is not free. section 2.1
Scheduling determines when execution changes hands:
- For kernel-level threads, the operating system keeps each thread’s registers, stack, and state, then intervenes to choose the next runnable thread. section 2.3.2
- Preemptive OS scheduling can use clock interrupts to stop a kernel thread after its CPU time and switch to another thread from the run queue. section 2.3.3
- A blocking I/O operation can also prompt a switch, allowing a single processor to give another job time while the first waits. section 2.4
- User-level threads shift scheduling and context switching into an application runtime, which maintains state for each thread without OS intervention. section 2.3.2
User-level switching is faster than kernel-level switching because the process can change execution without entering the kernel. This avoids the OS scheduling intervention and can avoid flushing the CPU cache, but it also makes the runtime responsible for tracking and scheduling its own threads. section 2.3.2
Giving a goroutine a chance to run
Starting `sayHello` with `go` creates a goroutine, but `main` can terminate before it runs. Calling `runtime.Gosched()` asks the Go scheduler to yield execution, increasing the chance that `sayHello` prints `Hello` before `Finished`. It does not guarantee that result: the scheduler may select `main` again, so concurrent code must not depend on a particular next goroutine. section 2.3.3
The figure distinguishes OS clock-driven switching from Go’s user-level scheduler, which needs events such as goroutine creation, system calls, or synchronization to run. section 2.3.3








