Review
A thread is a basic unit of CPU utilization.

Thread Concept
| Dimension | Process | Thread |
|---|---|---|
| Nature of the unit | An independent execution unit that can carry out tasks on its own and owns an independent set of resources | A subset of a process; cannot exist apart from its process; one process may contain multiple threads |
| State information | Holds a large amount of state, such as the process ID, state, memory-management information, list of file descriptors, etc. | Shares the process’s state, memory and other resources; maintains only a small amount of information such as the thread ID, program counter, register set and stack |
| Address space | Has its own address space; the address spaces of different processes are isolated from each other | Shares the address space of the process it belongs to |
| Communication | Relies on inter-process communication (IPC) mechanisms such as pipes, message queues, shared memory, semaphores, etc. | Besides IPC mechanisms, can also communicate directly through shared memory |
| Context switch | All state information must be saved and restored on a switch, involving a lot of data movement; expensive and relatively slow | Only a small amount of state needs to be saved and restored, and since the address space is shared there is no need to switch memory-management information; faster |

Pros:
- Handling many similar tasks
- Exploiting multicore systems
- Thread creation is lightweight
Examples:
- Client-server applications
- Most operating system kernels are multithreaded
Multicore Programming
| Dimension | Concurrency | Parallelism |
|---|---|---|
| Core definition | Handling multiple tasks “simultaneously” in a logical sense, achieved by switching between tasks | Executing multiple tasks simultaneously in a physical sense, relying on multiple cores or a distributed system |
| How it is achieved | Time-slice round-robin (e.g. OS thread scheduling) Multithreading, asynchronous I/O, event loops; a web server handling many requests (e.g. Nginx) | Directly allocating independent resources (e.g. multicore CPUs or distributed nodes) Multithreading, multiprocessing, GPU/TPU acceleration, distributed computing; scientific computing (e.g. weather simulation), image processing (e.g. GPU rendering) |
| Resource requirements | Low; a single-core CPU suffices | High; requires a multicore CPU or a distributed system |
| Suitable task types | I/O-bound (e.g. database queries, network requests) | Compute-bound (e.g. matrix operations, AI training) |
| Performance bottlenecks | Context-switch overhead, I/O latency | Task decomposability, communication overhead (in distributed settings) |
| Programming complexity | High; must deal with asynchronous logic and callback hell | Very high; must deal with synchronization and distributed consistency |
| Real-world applications | A browser rendering multiple tabs at once A chat server handling a large volume of user messages | Video rendering software using GPU acceleration A search engine crawling web pages in parallel across a cluster |
Parallelism
- Data Parallelism
- Mapreduce
- Distributed Machine Learning
- Task Parallelism
- Federated Submodel Learning
- Distributed Machine Learning
Amdahl’s Law
Formula:
- P: the proportion of the serial portion
- N: the number of parallel parts
It is determined by the proportion of the serial portion
Multithreading Models
| Dimension | Kernel Threads | User Threads |
|---|---|---|
| Core definition | Managed and scheduled directly by the OS kernel; visible to the kernel; assigned CPU time slices and resources directly; execute independently | Managed by a user-space thread library; invisible to the kernel; treated as lightweight tasks within a single process; rely on kernel threads to execute |
| Managed by | The operating system kernel | A user-space thread library (e.g. Pthreads, Java Threads) |
| Execution dependency | Execute independently, scheduled directly by the kernel | Depend on kernel threads to execute (must be mapped onto kernel threads) |
| Scheduling control | The kernel fully controls the scheduling policy (e.g. round-robin time slicing) | The user thread library schedules on its own (e.g. cooperative or preemptive) |
| Context-switch overhead | High (requires switching between kernel mode and user mode) | Low (switches only within user space) |
| Multicore utilization | Supports true parallelism (each kernel thread runs independently) | Limited by the number of kernel threads (must be mapped onto multiple cores) |
| Resource footprint | Each thread has its own kernel stack (usually large) | Share the process’s kernel stack; small user stacks (lightweight) |
| Effect of blocking | One thread blocking does not affect the others | If mapped onto the same kernel thread, blocking suspends all user threads |
| Suitable scenarios | Compute-intensive tasks, real-time systems | I/O-intensive tasks, high-concurrency scenarios |
| Typical implementations | Natively supported by operating systems such as Windows, Linux and macOS | Pthreads (POSIX), Java threads (early versions), Go’s Goroutines (hybrid model) |
| Mapping model | One-to-one (1:1); each kernel thread executes independently | Many-to-one (M:1): multiple user threads mapped onto one kernel thread (e.g. early Java threads); many-to-many (M:N): user threads dynamically mapped onto kernel threads (e.g. Linux’s NPTL, modern Java threads) |
| Advantages | Multicore parallelism, strong robustness, no blocking risk | Lightweight, high concurrency, fast context switches |
| Disadvantages | High context-switch overhead, high resource usage | Poor multicore utilization; blocking easily degrades performance |
| Plain-language analogy | Like full-time employees in a factory: the factory manager (the kernel) assigns tasks directly, everyone works independently, and one person taking leave (blocking) does not affect the others | Like an outsourced team in a factory: managed by a foreman (the thread library) and sharing one set of equipment (a kernel thread); if one person takes leave (blocks), the whole team may come to a halt |
| Real-world examples | Scientific computing (e.g. matrix operations), video rendering (using multicore GPUs) | Web servers handling many concurrent requests (e.g. Node.js’s event loop), multitasking in games (e.g. animation plus network communication) |

Lightweight process (LWP): A mapping between user threads and kernel threads
Multithreading models
| Dimension | Many-to-one (M:1) | One-to-one (1:1) | Many-to-many (M:N) |
|---|---|---|---|
| Mapping | Multiple user threads mapped onto one kernel thread | Each user thread mapped directly onto one kernel thread | User threads dynamically mapped onto multiple kernel threads |
| Kernel awareness | Invisible to the kernel; managed only by the user thread library | The kernel manages each thread directly | Visible to the kernel; user threads dynamically associated with kernel threads |
| Context-switch overhead | Low (switches only within user space) | High (requires switching between kernel mode and user mode) | Medium (combines the characteristics of both) |
| Multicore utilization | Cannot use multiple cores (limited to a single kernel thread) | Makes full use of multiple cores (each thread runs independently) | Uses multiple cores efficiently (kernel threads allocated dynamically) |
| Resource footprint | Low (shared kernel stack) | High (each thread has its own kernel stack) | Medium (kernel threads allocated on demand) |
| Effect of blocking | If the kernel thread blocks, all user threads are suspended | One thread blocking does not affect the others | When some threads block, the others can still run |
| Suitable scenarios | I/O-intensive tasks (e.g. early Java threads) | Compute-intensive tasks (e.g. scientific computing) | High-concurrency scenarios (e.g. web servers, Go Goroutines) |
| Typical implementations | Early Java threads (Solaris green threads), old-style LWPs (lightweight processes) | Linux kernel threads (the clone system call), Windows threads | GNU’s NPTL (the native Linux thread library), Java 1.2+, Go Goroutines |
| Advantages | Lightweight, fast context switches | Multicore parallelism, no blocking risk | Efficient multicore use, strong high-concurrency capability |
| Disadvantages | Cannot use multiple cores, high blocking risk | High resource usage, high context-switch overhead | High implementation complexity, requires dynamic scheduling |
| Plain-language analogy | One chef (kernel thread) handles multiple orders (user threads) at once, but can only cook one dish at a time (everything pauses when blocked) | Each order (user thread) is handled by its own chef (kernel thread); efficient, but more chefs must be hired (high resource consumption) | Chefs (kernel threads) are assigned dynamically according to the number of orders (user threads): more chefs at peak times, fewer when idle (balancing resources and efficiency) |
| Real-world scenarios | Early Java web servers (lightweight concurrency) | Video rendering, scientific computing (needs multicore parallelism) | Modern web servers (e.g. Node.js, Go), distributed systems (e.g. Kafka) |
Thread Libraries
Tools for manage threads
- POSIX Pthreads
- Java Threads
- Win32 Threads
Pthreads
1 |
|
Implicit Threading
- Thread Pools
- Create a number of threads in advance and have them wait for tasks to arrive
- Fork-Join
- Divide and conquer
- OpenMP
- A parallel programming interface
- Grand Central Dispatch
- Apple’s parallel programming framework
- Intel Threading Building Blocks
- Intel’s parallel programming framework
Threading Issues

On Kernel and User
Having studied operating systems up to this point, I have noticed the concepts of Kernel and User appearing everywhere, so here are some of my own explorations and thoughts.
Origins
Multics (1960s)
A time-sharing operating system developed jointly by MIT, Bell Labs and General Electric, which was the first to introduce a hierarchical protection mechanism (Protection Rings). The system is divided into multiple privilege levels (e.g. Ring 0 to Ring 3), where:- Kernel Mode: runs at the highest privilege level (e.g. Ring 0) and can access all hardware resources and system data.
- User Mode: runs at a lower privilege level (e.g. Ring 3) with restricted access to sensitive resources.
UNIX’s inheritance and simplification
When Ken Thompson and Dennis Ritchie at Bell Labs designed UNIX, they were inspired by Multics but simplified the protection mechanism, keeping only two modes:- Kernel mode: executes kernel code and operates the hardware directly.
- User mode: runs application programs, which request kernel services through system calls.
Why separate user mode from kernel mode?
- Security: prevents user programs from damaging the kernel, whether maliciously or by mistake.
- Stability: a crashing user program does not affect the kernel.
- Resource management: the kernel centrally schedules hardware resources (such as the CPU and memory).
Thoughts
The design philosophy behind kernel mode and user mode is a classic case of seizing the principal contradiction while setting aside the secondary ones. It also reflects strict hierarchical design.
Translated from the Chinese original.

