0% found this document useful (0 votes)
27 views

CSE2005 ETH Reference Material I Module2 Threads

Threads are lightweight processes that allow concurrent execution within a process. A thread shares the process's resources such as memory, file descriptors, etc. but has its own program counter, registers, and stack. Multiple threads allow a program to perform multiple tasks simultaneously. Thread libraries provide APIs for thread management. POSIX Pthreads is a common standard for multithreaded programming on Linux and Unix systems.

Uploaded by

Kanishka Malik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views

CSE2005 ETH Reference Material I Module2 Threads

Threads are lightweight processes that allow concurrent execution within a process. A thread shares the process's resources such as memory, file descriptors, etc. but has its own program counter, registers, and stack. Multiple threads allow a program to perform multiple tasks simultaneously. Thread libraries provide APIs for thread management. POSIX Pthreads is a common standard for multithreaded programming on Linux and Unix systems.

Uploaded by

Kanishka Malik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 39

Module2_Threads

Reference: “OPERATING SYSTEM


CONCEPTS”, ABRAHAM SILBERSCHATZ,
PETER BAER GALVIN, GREG GAGNE , Wiley
publications.
Thread Overview
• Thread: A fundamental unit of CPU utilization that forms the basis of multithreaded
computer systems

• Threads are mechanisms that permit an application to perform multiple tasks


concurrently.

• Thread is a basic unit of CPU utilization


– Thread ID
– Program counter
– Register set
– Stack

• A single program can contain multiple threads


– Threads share (Code, data, open files ) with other threads belonging to the same process (hence
a thread is a Light Weight Process (LWP))
• Code, data, open files
Single and Multithreaded Processes

heavyweight process lightweight process

Traditional (heavyweight) process has a single thread of control


Threads in Memory
Memory is allocated for a process in segments or
argv, environment
parts: Stack for main thread
Increasing virtual address

Stack for thread 1


Stack for thread 2
Stack for thread 3

Heap

Un-initialized data
Initialized data
Text ( program code)

Thread 1 executing here


Main thread executing here
Thread 3 executing here
Thread 2 executing here
0000000
Threads
Threads share…. Threads specific
Attributes….
• Global memory
• Process ID and parent  Thread ID
 Thread specific data
process ID  CPU affinity
• Controlling terminal  Stack (local variables and function
• Process credentials (user ) call linkage information)

• Open file information


• Timers
Benefits

 Responsiveness
Interactive application can delegate background functions to a thread and keep
running

 Resource Sharing
Several threads can access the same address space

 Economy
Allocating memory and new processes is costly. Threads are much ‘cheaper’ to
initiate.

 Scalability
Use threads to take advantage of multiprocessor architecture
Multithreaded Server Architecture

thread

thread

thread

thread
Threads and Multicore Programming

Concurrent Execution on a Single-core System

Parallel Execution on a Multicore System


Threads and Multicore Programming

• Multicore systems place pressure on programmers. Some


of the challenges include
– Dividing activities
• What tasks can be separated to run on different processors
– Balance
• Balance work on all processors
– Data splitting
• Separate data to run with the tasks
– Data dependency
• Watch for dependences between tasks
– Testing and debugging
• Harder!!!!
Threads Assist Multicore Programming

thread

thread

Let threads run on thread


different CPUs
thread
Multithreading Models
 Support provided at either

 User level -> user threads


Supported above the kernel and managed without
kernel support

 Kernel level -> kernel threads


Supported and managed directly by the operating
system
User Threads
• Thread management done by user-level
threads library

• Three primary thread libraries:


– POSIX Pthreads
– Win32 threads
– Java threads
Kernel Threads
• Supported by the Kernel

• Examples
– Windows XP/2000
– Solaris
– Linux
– Tru64 UNIX
– Mac OS X
Multithreading Models
User Thread – to - Kernel Thread

• Many-to-One

• One-to-One

• Many-to-Many
Many-to-One

Many user-level threads


mapped to single kernel
thread
One-to-One
Each user-level thread maps to kernel thread
 Examples
 Windows NT/XP/2000
 Linux
Many-to-Many Model
Allows many user level
threads to be mapped to
many kernel threads

Allows the operating


system to create a sufficient
number of kernel threads
 Example
 Windows NT/2000
with the
ThreadFiber
package
Thread Libraries
• Thread library provides programmer with API for creating
and managing threads

• Two primary ways of implementing


– Library entirely in user space
– Kernel-level library supported by the OS

• Three main thread libraries:


– POSIX Pthreads
– Win32
– Java
Thread Libraries
• Three main thread libraries in use :
– POSIX Pthreads
• May be provided either as user-level or kernel-level
• A POSIX standard (IEEE 1003.1c) API for thread creation and
synchronization
• API specifies behavior of the thread library, implementation is up to
development of the library
– Win32
• Kernel-level library on Windows system
– Java
• Java threads are managed by the JVM
• Typically implemented using the threads model provided by underlying
OS
POSIX Compilation on Linux

On Linux, programs that use the Pthreads API


must be compiled with
–pthread or –lpthread
POSIX: Thread Creation
#include <pthread.h>

pthread_create (thread, attr, start_routine, arg)

returns : 0 on success, some error code on failure.

Literally: 

int pthread_create(pthread_t *thread,


const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
POSIX: Thread ID
#include <pthread.h>

pthread_t pthread_self()

returns : ID of current (this) thread


POSIX: Wait for Thread Completion
#include <pthread.h>

pthread_join (thread, NULL)

 returns : 0 on success, some error code on failure.


 

- The thread calling pthread_join waits for the completion of


the thread passed to it as the first parameter.
- Second parameter is a pointer to the return value of the
thread that joins the caller.

int pthread_join(pthread_t thread, void **value_ptr);


POSIX: Thread Termination
#include <pthread.h>

Void pthread_exit (return_value)

Threads terminate in one of the following ways:


 The thread's start functions performs a return specifying a
return value for the thread.
 Thread receives a request asking it to terminate using
pthread_cancel()
 Thread initiates termination using pthread_exit()
 Main process terminates
Thread Cancellation
Terminating a thread before it has finished

Having made the cancellation request,


pthread_cancel() returns immediately; that is it
does not wait for the target thread to
terminate.

So, what happens to the target thread?


What happens and when it happens depends
on the thread’s cancellation state and type.
Thread Cancellation
Thread attributes that indicate cancellation state
and type

 Two general states


 Thread cannot be cancelled.
• PTHREAD_CANCEL_DISABLE

 Thread can be cancelled


• PTHREAD_CANCEL_ENABLE
• Default
Thread Cancellation
 When thread is cancelable, there are two general
types

 Asynchronous cancellation terminates the target


thread immediately
• PTHREAD_CANCEL_ASYNCHRONOUS

 Deferred cancellation allows the target thread to


periodically check if it should be cancelled
• PTHREAD_CANCEL_DEFERRED
• Cancel when thread reaches ‘cancellation point’
Thread Termination: Cleanup Handlers

Functions automatically executed when the


thread is canceled.

 Clean up global variables


 Unlock code or data held by thread
 Close files
 Commit or rollback transactions
Threading Issues
• Semantics of fork() and exec() system
calls
• Signal handling
• Thread pools
• Thread safety
• Thread-specific data
Semantics of fork() ,exec(), exit()
Does fork() duplicate only the calling thread or all threads?

 Threads and exec()


With exec(), the calling program is replaced in memory. All threads,
except the one calling exec(), vanish immediately. No thread-specific data
destructors or cleanup handlers are executed.

 Threads and exit()


If any thread calls exit() or the main thread does a return, ALL threads
immediately vanish. No thread-specific data destructors or cleanup
handlers are executed.
Semantics of fork() ,exec(), exit()
 Threads and fork()
When a multithread process calls fork(), only the calling thread
is replicated. All other threads vanish in the child. No thread-
specific data destructors or cleanup handlers are executed.
Problems:
 The global data may be inconsistent:
• Was another thread in the process of updating it?
• Data or critical code may be locked by another thread. That lock is
copied into child process, too.
 Thread (other) specific data not available
Signal Handling
• Signals are used in UNIX systems to notify a process
that a particular event has occurred
• A signal handler is used to process signals
1. Signal is generated by particular event
2. Signal is delivered to a process
3. Signal is handled
• Options:
– Deliver the signal to the thread to which the signal applies
– Deliver the signal to every thread in the process
– Deliver the signal to certain threads in the process
– Assign a specific thread to receive all signals for the process
Thread Pools
• Create a number of threads in a pool
where they await work
• Advantages:
– Usually slightly faster to service a request with
an existing thread than create a new thread
– Allows the number of threads in the
application(s) to be bound to the size of the
pool
Thread Safety
A function is thread-safe if it can be safely invoked by
multiple threads at the same time.
Example of a non safe function:
static int glob = 0;

static void Incr (int loops)


{
int loc, j;
for (j = 0; j<loops; j++ {
loc = glob;
loc++;
glob = loc;
}
}
Employs global or static values that are shared by all threads
POSIX compliation
On Linux, programs that use the Pthreads API must be compiled with
–pthread. The effects of this option include the following:

 _REENTRANT preprocessor macro is defined. This causes the declaration of a few


reentrant functions to be exposed.

 The program is linked with the libpthread library


(the equivalent of -lpthread )
 The precise options for compiling a multithreaded program vary across implementations
(and compilers).

From M. Kerrisk, The Linux Programming Interface

http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
http://codebase.eu/tutorial/posix-threads-c/
Threads vs. Processes
• Advantages of multithreading
– Sharing between threads is easy
– Faster creation
• Disadvantages of multithreading
– Ensure threads-safety
– Bug in one thread can spread to other threads, since they share the
same address space
– Threads must compete for memory
• Considerations
– Dealing with signals in threads is tricky
– All threads must run the same program
– Sharing of files, users, etc
Example 1
#include<stdio.h> if ( pthread_create( &thread1, NULL, thread1_fun, NULL )
<0 )
#include<pthread.h>
{
#include<stdlib.h>
perror("pthread_create");
#include<string.h> exit( 1 );
void * thread1_fun(void * a) { }
printf("Thread 1 is running.....\n\n");
printf("Thread 1's ID is %ld\n", pthread_self()); if ( pthread_create( &thread2, NULL, thread2_fun, NULL )<
0)
}
{
void * thread2_fun(void *address) { perror("pthread_create");
printf("Thread 2 is running.....\n\n"); exit( 1 );
printf("Thread 2's ID is %ld\n", pthread_self()); }
} pthread_join( thread1 , NULL);
int main() { pthread_join( thread2 , NULL);
printf("Main Thread is about to terminate\n");
pthread_t thread1, thread2;
printf("Main Thread has started running.....\n\n");
return 0;
printf("Main Thread's ID is %ld\n", }
pthread_self());
Example 2
#include<stdio.h> int main() {
#include<pthread.h> int n =5 ;
#include<stdlib.h> char str[50];
#include<string.h> strcpy(str, "VIT Vellore");
void * thread1_fun(void *num) { pthread_t thread1, thread2;
int *n = (int *) num; if ( pthread_create( &thread1, NULL, thread1_fun,
int i; (void *) &n ) <0 )
long fact =1; {
for( i = 1 ; i <= *n; i++) perror("pthread_create");
fact*= i; exit( 1 );
printf("The factorial of %d is %ld\n", *n , fact); }
}
void * thread2_fun(void *address) { if ( pthread_create( &thread2, NULL, thread2_fun,
char *str = (char *) address; (void *) str ) <0 )
int len = 0; {
for( len = 0 ; str[len] != '\0' ; len++ ) ; perror("pthread_create");
printf("The string length of %s is %d\n", str , exit( 1 );
len); }
} pthread_join( thread1 , NULL);
pthread_join( thread2 , NULL);
return 0;
}
 
Example 3
#include<stdio.h> int main() {
#include<pthread.h> int n =5 ;
#include<stdlib.h> char str[50];
#include<string.h> //Same as the previous program but thread1_fun strcpy(str, "VIT Vellore");
returns a value fact = (long *) malloc(sizeof(long));
long * fact; pthread_t thread1, thread2;
void * thread1_fun(void *num) { if ( pthread_create( &thread1, NULL, thread1_fun, (void *) &n ) <0 )
int *n = (int *) num; {
int i; perror("pthread_create");
*fact=1; exit( 1 );
for( i = 1 ; i <= *n; i++) }
*fact*= i;
printf("The factorial of %d is %ld\n", *n , *fact); if ( pthread_create( &thread2, NULL, thread2_fun, (void *) str ) <0 )
return fact; {
} perror("pthread_create");
void * thread2_fun(void *address) { exit( 1 );
char *str = (char *) address; }
int len = 0; pthread_join( thread1 , (void **)&fact);
for( len = 0 ; str[len] != '\0' ; len++ ) ; pthread_join( thread2 , NULL);
printf("The string length of %s is %d\n", str , len);
} printf("The factorial of %d is %ld\n", n , *fact);

return 0;
}

You might also like