CH 4 (Threads)
CH 4 (Threads)
CH 4 (Threads)
Threads Management
References:
Abraham Silberschatz, Greg Gagne, and Peter Baer Galvin, "Operating System Concepts, Ninth Edition ",
Chapter 4
Overview
A thread is a basic unit of CPU utilization, consisting of a program counter, a stack, and a set of
registers, ( and a thread ID. ) OR
A thread is a flow of execution through the process code, with its own program counter that keeps track of
which instruction to execute next, system registers which hold its current working variables, and a stack
which contains the execution history.
A thread shares with its peer threads few information like code segment, data segment and open files.
When one thread alters a code segment memory item, all other threads see that.
A thread is also called a lightweight process. Threads provide a way to improve application performance
through parallelism. Threads represent a software approach to improving performance of operating
system by reducing the overhead thread is equivalent to a classical process.
Each thread belongs to exactly one process and no thread can exist outside a process. Each thread
represents a separate flow of control. Threads have been successfully used in implementing network
servers and web server. They also provide a suitable foundation for parallel execution of applications on
shared memory multiprocessors.
Traditional ( heavyweight ) processes have a single thread of control - There is one program counter,
and one sequence of instructions that can be carried out at any given time.
As shown in Figure 4.1, multi-threaded applications have multiple threads within a single process, each
having their own program counter, stack and set of registers, but sharing common code, data, and certain
structures such as open files.
Single-threaded and multithreaded processes
Motivation
Threads are very useful in modern programming whenever a process has multiple tasks to perform
independently of the others.
This is particularly true when one of the tasks may block, and it is desired to allow the other tasks to
proceed without blocking.
For example in a word processor, a background thread may check spelling and grammar while a
foreground thread processes user input ( keystrokes ), while yet a third thread loads images from the
hard drive, and a fourth does periodic automatic backups of the file being edited.
Another example is a web server - Multiple threads allow for multiple requests to be satisfied
simultaneously, without having to service requests sequentially or to fork off separate processes for
every incoming request. ( The latter is how this sort of thing was done before the concept of threads
was developed. A daemon would listen at a port, fork off a child for every incoming request to be
processed, and then go back to listening to the port. )
Benefits
There are four major categories of benefits to multi-threading:
Responsiveness - One thread may provide rapid response while other threads are blocked or slowed
down doing intensive calculations.
Resource sharing - By default threads share common code, data, and other resources, which allows
multiple tasks to be performed simultaneously in a single address space.
Economy - Creating and managing threads ( and context switches between them ) is much faster than
performing the same tasks for processes.
Scalability, i.e. Utilization of multiprocessor architectures - A single threaded process can only run
on one CPU, no matter how many may be available, whereas the execution of a multi-threaded
application may be split amongst available processors. ( Note that single threaded processes can still
benefit from multi-processor architectures when there are multiple processes contending for the CPU,
i.e. when the load average is above some certain threshold. )
Multicore Programming
A recent trend in computer architecture is to produce chips with multiple cores, or CPUs on a single
chip.
A multi-threaded application running on a traditional single-core chip would have to interleave the
threads, as shown in Figure 4.3. On a multi-core chip, however, the threads could be spread across the
available cores, allowing true parallel processing as shown in Figure 4.4
Programming Challenges
For application programmers, there are five areas where multi-core chips present new
challenges:
1. Identifying and divided tasks - Examining applications to find activities that can be
performed concurrently.
For Example: Matrix Multiplication problem can be parallelized but Fibonacci series
problem cannot.
2. Load Balancing - Finding tasks to run concurrently that provide equal value. I.e. don't
waste a thread on trivial tasks.
3. Data splitting - To prevent the threads from interfering with one another.
4. Data dependency - If one task is dependent upon the results of another, then the tasks
need to be synchronized to assure access in the proper order.
5. Testing and debugging - Inherently more difficult in parallel processing situations, as
the race conditions become much more complex and difficult to identify.
Types of Parallelism
1. Data parallelism / (SIMD) divides the data up amongst multiple cores ( threads ), and
performs the same task on each subset of the data. For example dividing a large image up
into pieces and performing the same digital image processing on each piece on different
cores.
2. Task parallelism divides the different tasks to be performed among the different cores and
performs them simultaneously. One example of task parallelism would be an application
creating threads for doing parallel processing where each thread is responsible for performing
a different operation.
In practice no program is ever divided up solely by one or the other of these, but instead by some
sort of hybrid combination.
Types of Threads
There are two types of threads to be managed in a modern system: User threads and kernel
threads.
1. User Level Threads are supported above the kernel, without kernel support. These are the
threads that application programmers would put into their programs. In fact, the kernel
knows nothing about user-level threads and manages them as if they were single-threaded
processes.
Advantages:
Disadvantages:
In this case, thread management is done by the Kernel. There is no thread management code
in the application area. Kernel threads are supported directly by the operating system. Any
application can be programmed to be multithreaded. All of the threads within an application
are supported within a single process.
The Kernel maintains context information for the process as a whole and for individuals
threads within the process. Scheduling by the Kernel is done on a thread basis. The Kernel
performs thread creation, scheduling and management in Kernel space. Kernel threads are
generally slower to create and manage than the user threads.
Advantages:
1. Kernel can simultaneously schedule multiple threads from the same process on multiple
processes.
2. If one thread in a process is blocked, the Kernel can schedule another thread of the same
process.
3. Kernel routines themselves can be multithreaded.
Disadvantages:
1. Kernel threads are generally slower to create and manage than the user threads.
2. Transfer of control from one thread to another within the same process requires a mode
switch to the Kernel.
Multithreading Models
In a specific implementation, the user threads must be mapped to kernel threads, using one of the
following strategies. Some operating system provide a combined user level thread and Kernel
level thread facility. Solaris is a good example of this combined approach. In a combined system,
multiple threads within the same application can run in parallel on multiple processors and a
blocking system call need not block the entire process. Multithreading models are three types
1. Many-To-One Model
1. In the many-to-one model, many user-level threads are all mapped onto a single kernel
thread.
2. Thread management is handled by the thread library in user space, which is very
efficient.
3. However, if a blocking system call is made, then the entire process blocks, even if the
other user threads would otherwise be able to continue.
4. Because a single kernel thread can operate only on a single CPU, the many-to-one model
does not allow individual processes to be split across multiple CPUs.
5. Green threads for Solaris and GNU Portable Threads implement the many-to-one model
in the past, but few systems continue to do so today.
Many-to-one model
2. One-To-One Model
1. The one-to-one model creates a separate kernel thread to handle each user thread.
2. One-to-one model overcomes the problems listed above involving blocking system calls and the
splitting of processes across multiple CPUs.
3. However the overhead of managing the one-to-one model is more significant, involving more
overhead and slowing down the system.
4. Most implementations of this model place a limit on how many threads can be created.
5. Linux and Windows from 95 to XP implement the one-to-one model for threads.
3. Many-To-Many Model
1. The many-to-many model multiplexes any number of user threads onto an equal or
smaller number of kernel threads, combining the best features of the one-to-one and
many-to-one models.
2. Users have no restrictions on the number of threads created.
3. Blocking kernel system calls do not block the entire process.
4. Processes can be split across multiple processors.
5. Individual processes may be allocated variable numbers of kernel threads, depending on
the number of CPUs present and other factors.
Many-to-many model
6. One popular variation of the many-to-many model is the two-tier model, which allows either many-
to-many or one-to-one operation.
7. IRIX, HP-UX, and Tru64 UNIX use the two-tier model, as did Solaris prior to Solaris 9.