threads Flashcards
Thread Motivation
- Processes are expensive to create and maintain
– Context switch overhead between processes
– Process synchronization cumbersome
– Communication between processes must be done through an external structure - Files
- Pipes
- Sockets
- Shared memory
Processes and Threads
- Process considered to be heavyweight
– Ownership of memory, files, other resources - Threads
– A thread can be seen as lightweight process
– A unit of execution associated with a particular process, using many of the process’ resources
– Multithreading - Allowing multiple threads per process
– Benefits of multithreading - Responsiveness (minimize time, concurrency)
- Resource sharing (i.e., shared memory)
- Economy (creation, switch)
- Scalability (explore multi-core CPUs)
Process Properties
- Each process has its own:
– Program Counter (PC)
– Stack
– Stack Pointer (SP)
– Address space - Processes may share:
– Open files
– Pipes
Thread View
- Operating System Perspective
– An independent stream of instructions that can be scheduled to be run by the OS - Programmer Perspective
– Can be seen just as a “function” that executes independently from the main program
– A single stream of instructions in a program - Multiple threads can share a process
– Multiple flows of control within a process
– Share code and data space of process
– Lower overhead, avoid context switches
Thread Execution Environment
The process is the execution environment for a family of threads
– A group of threads share the same resources (files, memory space, etc.)
* Since threads are associated with their process, they are able to use the resources belonging to the process and duplicate only the required resources, such as the PC, stack, and SP, needed by the OS to schedule threads independently from their processes
– This makes creating and switching between threads belonging to same process very simple and much more efficient than creating or switching between processes
* Although switching for threads belonging to different processes is still as complex as classic process switch
Thread Properties
- Each thread has its own:
– Program Counter (PC)
– Stack
– Stack Pointer (SP)
– Registers
– Scheduling properties
– Set of pending/blocked signals
– Thread specific data - Threads share:
– Address space - Variables
- Code
– Open files
Since a thread exists within a process, if a process terminates, so does the thread
Thread Consequences
- Since threads within the same process share resources
- Changes made by one thread to shared system resources (such as closing a file) will be seen by all other threads
– Any files opened inside a thread will remain open (unless explicitly closed) even after the thread is terminated - Two pointers having the same value point to the same data
- Reading and writing to the same memory locations is possible
– Therefore requires explicit synchronization by the programme
POSIX Threads
- The most commonly used thread package on Linux is POSIX threads (also known as pthreads)
– Standards-based API to create, manage, and synchronize threads - Thread package includes library calls for
– Thread management (creation, destruction)
– Mutual exclusion (synchronization, short-term locking)
– Condition variables (waiting on events of unbounded duration) - A run-time system manages threads in a transparent manner so that the user is unaware
– Robust programs should not depend upon threads executing in a specific order
The pthreads Library
The pthread.h library includes the following operations:
– pthread_create create a new thread
– pthread_detach detach a thread, to release its resources when thread terminates
– pthread_exit terminate calling thread, without terminating process
– pthread_join wait for a specified thread to terminate
– pthread_equal compare thread IDs
– pthread_kill send a specified signal to a thread
– pthread_self obtain the ID of the calling thread
Creating Threads
int pthread_create(pthread_t tid, const pthread_attr_t tattr, void (start_routine)(void *), void *arg);
– tid: an unsigned long integer that indicates a thread’s id
– tattr: attributes of the thread – usually NULL
– start_routine: the name of the function the thread starts executing
– arg: the argument to be passed to the start routine – only one
- pthread_create( tid, NULL, void (*start_routine), void *arg);
- After this function gets executed, a new thread has been created and is executing the function indicated by start_routine
- Once created, threads are peers, and may create other threads
- There is no implied hierarchy or dependency between threads
Joining Threads
Joining is one way to accomplish synchronization between threads where the process waits for all threads to complete
– We call the function pthread_join() once for each thread
Wait for Completion of a Thread
int pthread_join(thread_t tid, void **status);
– tid: identification of the thread to wait for
– status: the exit status of the terminating thread – can be NULL
- The process that calls this pthread_join function blocks its own execution until the thread indicated by tid terminates its execution
– Finishes the function it started with, or
– Issues a pthread_exit() command
Exiting a Thread
- pthreads exist in user space and are seen by the kernel as a single process
– If one issues an exit() system call, all the threads are terminated by the OS
– If the main() function exits, all of the other threads are terminated - To have a thread exit, use pthread_exit()
void pthread_exit(void *status);
– status: the exit status of the thread – passed to the status variable in the pthread_join() function of a thread waiting for this one
Detaching a Thread
- Indicates that system resources for the specified thread should be reclaimed when thread ends
– If the thread has already ended, resources are reclaimed immediately
– This routine does not cause the thread to end! - Threads are detached
– After a pthread_detach() call
– After a pthread_join() call
– If a thread terminates and PTHREAD_CREATE_DETACHED attribute was set on creation - Failure to join or detach threads – memory and other resources will leak until the process ends
int pthread_detach(pthread_t tid);
– tid: identification of the thread to detach
Memory in Processes vs Threads
- Each thread will have its own stack, but all the threads in a process will share the heap.
- Threads are sometimes called lightweight processes because they have their own stack but can access shared data.
- Because threads share the same address space as the process and other threads within the process, the operational cost of communication between the threads is low, which is an advantage.
Thread Safety
- The threads for a process share the entire address space of the process
- This means, threads can modify global variables, access open file descriptors, etc.
– Be careful when reusing variables passed by reference - So, we need to ensure that multiple threads do not interfere with each other – synchronize thread execution
- A program or function is said to be thread safe if it can be called from multiple threads without unwanted interaction between the threads
– That is, it should be able to execute multiple threads simultaneously without “clobbering” shared data or creating “race” conditions