Understanding Processes, Threads, and Goroutines: From OS Scheduler to Go Concurrency
This article explains the fundamentals of operating‑system processes and threads, how the OS scheduler enables concurrent execution, the cost of context switches, and why Go implements lightweight user‑level goroutines to achieve efficient concurrency in modern applications.
1 Introduction
Hello Gopher! Thanks to Go's built‑in concurrency, many engineers have entered the world of concurrent programming, but they still encounter memory leaks, data races, and deadlocks. The article poses three questions: what is concurrency, why does Go implement goroutines, and how does Go achieve concurrency.
2 Processes and Threads
An operating system manages both software and hardware, and its two core concepts are processes and threads. A process is an independent execution environment with its own memory and resources, while a thread is a lightweight scheduling unit that runs within a process.
When a program starts, the OS creates a process and a main thread; the process holds memory, the thread holds CPU time. Multiple threads run independently, taking turns on the CPU.
3 Thread Concurrency
On a single‑core CPU, true simultaneous execution is impossible; the illusion of parallelism comes from rapid context switching, similar to how a high frame‑rate creates smooth video.
The OS scheduler decides when a thread runs, based on three states: Waiting (blocked), Runnable (ready), and Executing (running). It allocates time slices, preempts threads when their slice expires, and switches to another runnable thread.
4 OS Scheduler
The scheduler gives each thread a limited time slice, forces a switch when the slice ends, and may preempt a thread that becomes blocked, allowing another thread to use the CPU.
5 Context Switch
Switching involves saving the current thread's stack, instruction pointer, and resources, then restoring the next thread's state. This operation costs roughly 1 µs (≈1000 ns) and wastes CPU cycles.
6 Coroutines
To reduce the overhead of kernel‑level context switches, user‑level threads (coroutines) were introduced. User‑mode threads run in user space, are scheduled by the application, and have much lower switching costs.
Coroutines are cooperative multitasking constructs; they run on a single kernel thread and switch only when the program yields control.
7 Goroutine
Go implements goroutines as user‑level coroutines. The Go scheduler manages three entities: G (goroutine), M (machine, i.e., kernel thread), and P (processor, a logical resource that schedules G onto M). This G‑M‑P model balances CPU utilization and low‑cost switching.
8 Conclusion and Next Steps
The article recaps that threads are the OS scheduling unit, concurrency is achieved via context switches, and those switches have a time cost. It introduces goroutines as a way to mitigate this cost and previews the next article, which will dive into the Go scheduler, GC interaction, and common concurrency pitfalls.
Beike Product & Technology
As Beike's official product and technology account, we are committed to building a platform for sharing Beike's product and technology insights, targeting internet/O2O developers and product professionals. We share high-quality original articles, tech salon events, and recruitment information weekly. Welcome to follow us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.