University of Central Punjab
FOIT (Operating Systems)
Threads
Objective
• Students will be able to create multiple threads
in a program.
• Students will be able to get and set various
attributes of a thread.
• Students will be able to pass parameters to a
thread and return a value from it.
• Students will be able to cancel the
threads instantly or at a safe point.
• Students will be able to break a large
problem among various threads to achieve
speedup.
University of Central Punjab
FOIT (Operating Systems)
Threads
What is a Thread?
A thread is a flow of control within a process. A process can
contain multiple threads.
Why Multithreading?
A thread is also known as lightweight process. The idea is to
achieve parallelism by dividing a process into multiple
threads. For example, in a browser, multiple tabs can be
different threads. MS Word uses multiple threads: one thread
to format the text, another thread to process inputs, etc.
More advantages of multithreading are discussed below Process
vs Thread?
The primary difference is that threads within the same process
run in a shared memory space, while processes run in separate
memory spaces.
Threads are not independent of one another like processes
are, and as a result thread share with other threads their
code section, data section, and OS resources (like open files
and signals). But, like process, a thread has its own program
counter (PC), register set, and stack space.
Advantages of Thread over Process
1. Responsiveness: If the process is divided into multiple
threads, if one thread completes its execution, then its
output can be immediately returned.
2. Faster context switch: Context switch time between threads
is lower compared to process context switch. Process context
switching requires more overhead from the CPU.
3. Effective utilization of multiprocessor system: If we have
multiple threads in a single process, then we can schedule
multiple threads on multiple processors. This will make
process execution faster.
4. Resource sharing: Resources like code, data, and files can
be shared among all threads within a process.
Note: stack and registers can’t be shared among the threads.
Each thread has its own stack and registers.
5. Communication: Communication between multiple threads is
easier, as the threads shares common address space. while in
process we have to follow some specific communication
technique for communication between two processes.
6. Enhanced throughput of the system: If a process is divided
into multiple threads, and each thread function is considered
University of Central Punjab
FOIT (Operating Systems)
Threads
as one job, then the number of jobs completed per unit of
time is increased, thus increasing the throughput of the
system. #include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t
*attr, void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
The pthread_create() function starts a new thread in the
calling process. The new thread starts execution by invoking
start_routine(); arg is passed as the sole argument of
start_routine().
The attr argument points to a pthread_attr_t structure whose
contents are used at thread creation time to determine
attributes for the new thread; this structure is initialized
using pthread_attr_init(3) and related functions. If attr is
NULL, then the thread is created with default attributes.
Before returning, a successful call to pthread_create()
stores the ID of the new thread in the buffer pointed to by
thread; this identifier is used to refer to the thread in
subsequent calls to other pthreads functions.
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
Compile and link with -pthread.
The pthread_join() function waits for the thread specified by
thread to terminate. If that thread has already terminated,
then pthread_join() returns immediately. The thread
specified by thread must be joinable.
If retval is not NULL, then pthread_join() copies the exit
status of the target thread (i.e., the value that the target
thread supplied to pthread_exit(3)) into the location pointed
to by retval. If the target thread was canceled, then
PTHREAD_CANCELED is placed in the location pointed to by
retval.
On success, pthread_join() returns 0; on error, it returns an
error number.
University of Central Punjab
FOIT (Operating Systems)
Threads
Example: Pthread Creation and Termination
This simple example code creates 5 threads with the
pthread_create() routine. Each thread prints a "Hello World!"
message, and then terminates with a call to pthread_exit().
Creating Hello World Threads
University of Central Punjab
FOIT (Operating Systems)
Threads
Example: Parameter passing and returning value from a thread.
In this example, we will see how we can pass a structure and an
array to two different threads and returning value from them.
Passing parameters and returning values from Threads
University of Central Punjab
FOIT (Operating Systems)
Threads
#include <pthread.h>
int pthread_cancel(pthread_t thread);
Compile and link with - pthread.
The pthread_cancel() function sends a cancellation request to
the thread thread. Whether and when the target thread reacts to
the cancellation request depends on two attributes that are
under the control of that thread: its cancelability state and
type.
A thread's cancelability state, determined by
pthread_setcancelstate(3), can be enabled (the default for new
threads) or disabled. If a thread has disabled cancellation,
then a cancellation request remains queued until the thread
enables cancellation. If a thread has enabled cancellation,
then its cancelability type determines when cancellation
occurs.
A thread's cancellation type, determined by
pthread_setcanceltype(3), may be either asynchronous or
deferred (the default for new threads). Asynchronous
cancelability means that the thread can be canceled at any time
(usually immediately, but the system does not guarantee this).
Deferred cancelability means that cancellation will be delayed
until the thread next calls a function pthread_testcancel() at
cancellation point.
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
Compile and link with -pthread.
The pthread_setcancelstate() sets the cancelability state of
the calling thread to the value given in the state. The
previous cancelability state of the thread is returned in the
buffer pointed to by the oldstate. The state argument must
have one of the following values:
PTHREAD_CANCEL_ENABLE
The thread is cancelable. This is the default cancelability
state in all new threads, including the initial thread. The
thread's cancelability type determines when a cancellable
thread will respond to a cancellation request.
PTHREAD_CANCEL_DISABLE
University of Central Punjab
FOIT (Operating Systems)
Threads
The thread is not cancelable. If a cancellation request is
received, it is blocked until cancelability is enabled.
The pthread_setcanceltype() sets the cancelability type of the
calling thread to the value given in type. The previous
cancelability type of the thread is returned in the buffer
pointed to by oldtype. The type argument must have one of the
following values:
PTHREAD_CANCEL_DEFERRED
A cancellation request is deferred until the thread next calls
a function that is the cancellation point. This is the default
cancelability type in all new threads, including the initial
thread. Even with deferred cancellation, a cancellation point
in an asynchronous signal handler may still be acted upon and
the effect is as if it was an asynchronous cancellation.
PTHREAD_CANCEL_ASYNCHRONOUS
The thread can be canceled at any time. (Typically, it will be
canceled immediately upon receiving a cancellation request,
but the system doesn't guarantee this.)
The set-and-get operation performed by each of these
functions is atomic with respect to other threads in the
process calling the same function.
On success, these functions return 0; on error, they return a
nonzero error number.
University of Central Punjab
FOIT (Operating Systems)
GL- 8
Threads
Example: In the given example, we will create two threads. One
thread will change its cancel type to Asynchronous and other to
Deffered. The one with asynchronous type is cancelled instantly
while the other requires pthread_testcancel() to be called for
its cancellation.
Thread cancellation & changing cancellation type
University of Central Punjab
FOIT (Operating Systems)
Threads
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Compile and link with -pthread.
The pthread_attr_init() function initializes the thread
attributes object pointed to by attr with default attribute
values. After this call, individual attributes of the object
can be set using various related functions, and then the object
can be used in one or more pthread_create(3) calls that create
threads.
Calling pthread_attr_init() on a thread attributes object that
has already been initialized results in undefined behavior.
When a thread attributes object is no longer required, it
should be destroyed using the read_attr_destroy() function.
Destroying a thread attributes object has no effect on threads
that were created using that object.
Once a thread attributes object has been destroyed, it can be
reinitialized using pthread_attr_init(). Any other use of a
destroyed thread attributes object has undefined results.
On success, these functions return 0; on error, they return a
nonzero error number.
#include <pthread.h>
int pthread_attr_setstack(pthread_attr_t *attr, void
*stackaddr, size_t stacksize);
int pthread_attr_getstack(const pthread_attr_t *attr, void
**stackaddr, size_t *stacksize);
Compile and link with -pthread.
The pthread_attr_setstack() function sets the stack address and
stack size attributes of the thread attributes object referred
to by attr to the values specified in stackaddr and stacksize,
respectively. These attributes specify the location and size of
the stack that should be used by a thread that is created using
the thread attributes object attr. stackaddr should point to the
lowest addressable byte of a buffer of stacksize bytes that was
allocated by the caller. The pages of the allocated buffer
should be both readable and writable.
University of Central Punjab
FOIT (Operating Systems)
Threads
The pthread_attr_getstack() function returns the stack address
and stack size attributes of the thread attributes object
referred to by attr in the buffers pointed to by stackaddr and
stacksize,respectively.
On success, these functions return 0; on error, they return a
nonzero error number.
Example: In this example, we will initialize a variable with
default attributes. We will get the stack size from attribute
variable and display it. We will then set the size of stack to
16 MB.
Getting & setting stack size in pthread attributes
University of Central Punjab
FOIT (Operating Systems)
Threads
Task 1(to be submitted in the class)
Write a multithreaded program that calculates various
statistical values for a list of numbers. This program will be
passed a series of numbers on the command line and will then
create two separate worker threads. One thread will determine
the even numbers and the second will determine the odd numbers.
Example:
Input:
./[Link] 90 81 78 95 79 72 85
Output:
The even numbers are: 90 78 72
The odd numbers are: 81 95 79 85
Task 2(to be submitted in the class)
Task 3(Home task to be submitted before 11:55PM)
Write a program that is passed a filename, a number N and a
string S through command-line argument. The program opens a
file to search for a string S using N number of threads. If
any of the threads find sting S, it prints an appropriate
message along with line and column number and exits. The other
threads will also exit immediately once the string is found
by any thread.
Task 4:
Multithreaded Chat Application with Pipes
Problem: Develop a simple chat application that uses threads
and pipes for communication between multiple users. Each user
will have a dedicated pipe for sending and receiving messages.
University of Central Punjab
Requirements:
1. Use pipe to create a communication channel for each user.
2. Implement a thread for each user that continuously reads
from its input pipe and writes to its output pipe.
3. Each user should be able to send messages to other users by
writing to the appropriate pipe.
4. Implement a mechanism to handle message display (e.g.,
prefix messages with the sender's name).
5. Ensure that the application handles user termination
gracefully and cleans up resources.
Task-5:
Real-Time Stock Price Tracker
Problem: Develop a multithreaded application that monitors
stock prices from multiple sources. Each thread will
retrieve stock prices and communicate them via pipes to a
central processing thread.
Requirements:
1. Create multiple threads, each responsible for retrieving
stock prices from a different source (e.g., simulated by
random numbers).
2. Use pipe to send the retrieved stock prices to a central
thread.
3. The central thread should read from the pipe, calculate the
average price for each stock, and write the results to an
output file using write.
4. Implement proper error handling and ensure that all threads
are joined before exiting the program.
5. Use mutexes to synchronize access to shared data, ensuring
data integrity.
Question 2: Multithreaded Web Scraper
Problem: Create a multithreaded web scraper that fetches
data from multiple URLs concurrently. Each thread will
fetch data and send it to a central processing thread via
FIFO.
Requirements:
1. Use mkfifo to create a named pipe for communication between
the fetching threads and the processing thread.
2. Implement multiple threads that each fetch data from a
specified URL and write the results to the FIFO.
University of Central Punjab
3. Implement a processing thread that reads from the FIFO,
processes the data (e.g., extracts specific information),
and writes the processed data to a file.
4. Ensure proper error handling for network requests and file
operations.
5. Clean up resources, including deleting the FIFO after use.
Notification System
Problem: Build a multithreaded notification system that
listens for events from various sources and sends
notifications to users via FIFO.
Requirements:
1. Create multiple threads that simulate event sources (e.g.,
user actions, system events).
2. Use mkfifo to create a named pipe for sending
notifications.
3. Each event source thread should send a notification message
to the FIFO when an event occurs.
4. Implement a notification handler thread that reads from the
FIFO and displays notifications to the console.
5. Ensure that the application can gracefully handle the
termination of threads and FIFO cleanup.