NOTE
2.7 Programs, Processes, and Threads
The relationship between programs, processes, threads, and user-space tasks, including address spaces, scheduling, isolation, and context-switch costs.
This is a historical learning note and may contain outdated or incomplete understanding.
1. Program, Process, and Thread
A program is executable code and data stored as a passive artifact.
A process is a running instance with an address space and OS-managed resources such as file descriptors, credentials, and mappings.
A thread is an execution stream within a process. Threads in the same process normally share the process address space and many resources while keeping their own registers and stacks.
2. Process States
A simplified model has three important states:
- running — currently executing on a CPU;
- ready/runnable — able to execute but waiting for CPU time;
- blocked/waiting — waiting for an event such as I/O, a lock, or a timer.
Real kernels maintain more detailed states, but this model is sufficient for most scheduling discussions.
3. Processes vs. Threads
| Property | Process | Thread |
|---|---|---|
| Address space | normally isolated | shared with sibling threads |
| Resource ownership | process-level | mostly shared from process |
| Scheduling | schedulable entity depending on OS model | schedulable entity on mainstream OSes |
| Communication | IPC or shared mappings | ordinary shared memory |
| Failure isolation | stronger | weaker |
Thread switches are often cheaper than full process switches because sibling threads share an address space. The exact cost depends on architecture, TLB behavior, caches, kernel version, and whether the switch also changes memory mappings.
4. User-Space Tasks and Coroutines
A runtime can multiplex many user-space tasks over fewer OS threads. Go goroutines are one example.
Common mapping models are:
- N:1 — many user tasks on one thread; cheap scheduling but one blocking thread can stall all tasks unless the runtime avoids blocking operations;
- 1:1 — one user task per OS thread; simple but thread count and kernel scheduling become the scaling limit;
- M:N — many user tasks multiplexed over multiple OS threads; more complex but combines user-space scheduling with multicore execution.
Modern coroutine/goroutine systems are not necessarily purely cooperative. For example, modern Go supports runtime-driven preemption in addition to cooperative safe points.
5. Key Idea
A process is primarily an isolation/resource container. A thread is primarily an execution context. User-space runtimes can introduce another scheduling layer on top of OS threads.