Motivation
A process is expensive, as it requires process creation and context switches.
Communication between processes is difficult, as each process has an independent memory space, meaning it requires inter-process communication (IPC).
The general idea is that every traditional process has a single thread of control - meaning only one instruction of the whole program is executing at any time. Thus, adding more threads of control allows multiple parts to execute at the same time conceptually.
A multithreaded process is a process with multiple threads.
Thread
Each thread requires unique information such as
- Identification (thread id)
- Registers
- Stack
Benefits
Multiple threads in the same process require much less resources to manage compared to multiple processes - economy.
Threads share most of the resources, thus there is no need for additional mechanism for passing information around (as compared to with processes, and IPC) - resource sharing
Multithread programs are often appear much more responsive and can take advantage of multiple CPUs - scalability.
Problems
System call concurrency means that there are parallel execution of multiple threads, meaning parallel system calls are possible.
There are also impact on process operations
- if
fork
duplicates process, what about threads? - if a thread executes
exit()
, what about the other threads in the process, and the whole process? - if a single thread calls
exec()
, how about other threads?
Thread Models
Threads can be implemented either as user or kernel threads.
User Thread
User thread
Thread is implemented as a user library
A runtime system in the process will handle the thread related operations. The kernel is not aware of threads in the process.
Pros
- Multithreaded programs are OS-independent
- Thread operations are just library calls
- More configurable and flexible, with a customised thread scheduling policy
Cons
- OS not aware of threads, meaning scheduling is still performed at process level
- If a thread is blocked, the entire process is blocked, meaning all threads are blocked
- Prevents optimal utilisation of multiple CPUs
Kernel Thread
Kernel thread
Thread implemented in the OS
Thread operation is handled as system calls, allowing for thread-level scheduling instead of process-level scheduling. This means that the kernel might make use of threads for its own execution.
Pros
- Kernel can schedule on thread levels
- Allows more than 1 thread in the same process to run simultaneously
Cons
- Thread operations as a system call makes it slower and more resource intensive
- Less flexible
- Can be expensive for simple program if feature-rich
- Can be not flexible enough for complex program if feature-poor
Hybrid Thread
This model offers both Kernel and User threads, allowing for
- OS scheduling on kernel threads
- User thread binding to kernel threads
This model is more flexible, as it allows the limiting of concurrency of any process/user.
POSIX Threads pthread
pthread
is a standard defined by the IEEE, which is supported by most Unix variants.
The standard defines the API, and the behaviour, but the implementation is not, meaning the pthread
can be implemented as user/kernel thread.
Thread Creation
#include <pthread.h>
int pthread_create(
pthread_t *tidCreated,
const pthread_attr_t *threadAttributes,
void* (*startRoutine) (void*)
void *argForStartRoutine);
gcc XXXX.c -lpthread
Some datatypes that are relevant:
pthread_t
refers to the thread ID datatypepthread_attr
refers to the attributes of a thread datatype
The function takes in
tidCreated
: the thread ID of the created threadthreadAttributes
: attributes to control the behaviour of the new threadstartRoutine
: function pointer to the function to be executed by threadargForStartRoutine
: arguments for thestartRoutine
function
The function returns
0
if there is no error!0
if there is errors
Thread Exit
#include <pthread.h>
void pthread_exit(void* exitValue);
The function takes in
exitValue
: a value to be returned to any synchronised with this thread
If the pthread_exit()
is not used, it will terminate when the end of the startRoutine
is reached, but this does not return a exit value
Thread Join
#include <pthread.h>
int pthread_join(pthread_T threadID,
void **status);
The function takes in
threadID
: TID for thepthread
to wait forstatus
: Exit value returned by the targetpthread
The function returns
0
if there is no error!0
if there is errors