Learning outcomes
- Summarise various models for thread management and mapping user threads to kernel threads.
Understand how threads are managed, how user threads are mapped to kernel threads, and why different mapping models lead to different performance, blocking behaviour, and parallelism.
A process may contain multiple threads of execution. Each thread represents an independent sequence of instructions, while sharing the process code, data, and other resources. Thread management is important because the operating system must decide how threads are created, scheduled, supported by libraries, and mapped to the kernel.
The main design question is: How should user-level threads be mapped to kernel threads? The answer leads to different thread models, each with its own strengths and limitations.
These are threads managed in user space by a thread library. The kernel may not know about each individual user thread.
These are threads managed directly by the operating system kernel. The kernel schedules them like schedulable execution entities.
A thread library provides the programmer with an API for creating and managing threads. Thread libraries may be implemented in two main ways:
Common thread libraries include POSIX Pthreads, Windows threads, and Java threads. In practice, Java threads are often implemented using the host operating system’s thread support.
The mapping model describes the relation between user threads and kernel threads. This mapping strongly affects performance, blocking, and the ability to use multiple CPU cores.
In the many-to-one model, many user-level threads are mapped to one kernel thread.
Advantages:
Disadvantages:
This model is historically important, but it is rarely used now because it does not exploit modern multicore processors well.
In the one-to-one model, each user thread is mapped to one kernel thread.
Advantages:
Disadvantages:
Modern operating systems such as Linux and the Windows family commonly use this model.
In the many-to-many model, many user threads are multiplexed to a smaller or equal number of kernel threads.
Advantages:
Disadvantages:
This model is conceptually attractive, but many modern operating systems have moved away from it because implementation complexity is high and multicore processors have become common.
The two-level model is a variation of the many-to-many model. It still multiplexes many user threads to a smaller or equal number of kernel threads, but it also allows a particular user thread to be bound to a specific kernel thread.
Why this is useful:
| Model | Mapping | Blocking Effect | Parallelism | Main Issue |
|---|---|---|---|---|
| Many-to-One | Many user threads → 1 kernel thread | One blocking call may block entire process | No true parallelism | Cannot exploit multicore systems well |
| One-to-One | 1 user thread → 1 kernel thread | Another thread may continue if one blocks | Yes | Higher kernel-thread overhead |
| Many-to-Many | Many user threads → fewer/equal kernel threads | Better than many-to-one | Yes | Complex implementation |
| Two-Level | Many-to-many + optional binding | Better flexibility | Yes | Also complex |
Although the many-to-many model appears flexible, most modern operating systems now prefer the one-to-one model. The reason is simple: with multicore systems now standard, operating systems benefit from direct kernel scheduling of threads, even though the model may create more kernel-thread overhead.
Suppose a web server process creates three user threads:
Assume that T2 performs a blocking system call while reading from disk. Let us compare what happens under different thread models.
Conclusion: The many-to-one model is weakest when blocking system calls occur, because the whole process may stall. The one-to-one and many-to-many models support much better concurrency. On modern multicore systems, this is one major reason why the one-to-one model is widely adopted.
Thread management in an operating system deals with how threads are created, controlled, and mapped for execution. A thread library provides the API for thread creation and management. Thread libraries may exist entirely in user space or may be supported directly by the operating system kernel.
Threads can be viewed as user-level threads or kernel-level threads. User threads are managed by a thread library in user space, while kernel threads are managed and scheduled directly by the operating system. The relation between these two gives rise to different thread mapping models.
In the many-to-one model, many user threads are mapped to one kernel thread. This is efficient in user space, but if one thread blocks, the whole process may block. Also, it does not allow true parallel execution on multicore systems.
In the one-to-one model, each user thread is mapped to one kernel thread. This gives better concurrency and allows multiple threads to run in parallel on multiprocessors. However, creating many kernel threads increases overhead.
In the many-to-many model, many user threads are multiplexed to a smaller or equal number of kernel threads. This gives both flexibility and parallelism, but the model is more difficult to implement.
The two-level model is a variation of many-to-many mapping. It still supports multiplexing, but it also allows a particular user thread to be bound to a specific kernel thread.
The practical trend in modern operating systems is toward the one-to-one model. This is because multicore processors are now standard, and operating systems benefit from direct kernel scheduling of threads despite the added overhead.
In short, thread models are not just naming conventions. They directly affect responsiveness, scalability, and the ability of a system to use multiple CPU cores effectively.