CS211 Lec 15

Download as pdf or txt
Download as pdf or txt
You are on page 1of 21

Operating Systems

Course Code: CS211


Instructor: Dr. Sarah Iqbal

Lecture # 15
Agenda for Today
 Thread models
 Pthreads library with examples
Thread Libraries
 A thread library provides the programmer with an API for creating
and managing threads. There are two primary ways of implementing
a thread library.
 The first approach is to provide a library entirely in user space with
no kernel support. All code and data structures for the library exist in
user space. This means that invoking a function in the library results
in a local function call in user space and not a system call.
 The second approach is to implement a kernel-level library
supported directly by the operating system. In this case, code and
data structures for the library exist in kernel space. Invoking a
function in the API for the library typically results in a system call to
the kernel.
Thread Libraries…
 Three main thread libraries are in use today:
1. POSIX Pthreads,
2. Windows, and
3. Java.
 Pthreads, the threads extension of the POSIX standard, may be
provided as either a user-level or a kernel-level library.
 The Windows thread library is a kernel-level library available on
Windows systems.
 The Java thread API allows threads to be created and managed
directly in Java programs.
Thread Libraries…
 Two general strategies for creating multiple threads:
1. asynchronous threading
2. synchronous threading.

 With asynchronous threading, once the parent creates a child


thread, the parent resumes its execution, so that the parent and
child execute concurrently and independently of one another.
Because the threads are independent, there is typically little data
sharing between them.
 Asynchronous threading is the strategy used in the multithreaded
server and is also commonly used for designing responsive user
interfaces.
Thread Libraries…
 Synchronous threading occurs when the parent thread creates one
or more children and then must wait for all of its children to
terminate before it resumes. Here, the threads created by the
parent perform work concurrently, but the parent cannot continue
until this work has been completed.
 Once each thread has finished its work, it terminates and joins with
its parent. Only after all of the children have joined can the parent
resume execution.
 Typically, synchronous threading involves significant data sharing
among threads. For example, the parent thread may combine the
results calculated by its various children.
Pthreads
Pthreads refers to the POSIX standard (IEEE 1003.1c)
defining an API for thread creation and
synchronization.
This is a specification for thread behavior, not an
implementation. Operating-system designers may
implement the specification in any way they wish.
Numerous systems implement the Pthreads
specification; most are UNIX-type systems, including
Linux and macOS.
Although Windows doesn’t support Pthreads
natively, some third-party implementations for
Windows are available.
Creating a Thread
int pthread_create (pthread_t *threadp, const
pthread_attr_t *attr, void* (*routine)(void *), arg *arg);
threadp The thread we are trying to create—thread ID (TID)
attr Used to modify the thread attributes (stack size,
stack address, detached, joinable, priority, etc.)
routine The thread function
arg Any argument we want to pass to the thread
function. This does not have to be a simple
native type, it can be a ‘struct’ of whatever we
want to pass in.
Error Handling
pthread_create() fails and returns the corresponding
value if any of the following conditions is detected:
 EAGAIN The system-imposed limit on the total number of
threads in a process has been exceeded or some system resource
has been exceeded (for example, too many LWPs were created).
 EINVAL The value specified by attr is invalid.
 ENOMEM Not enough memory was available to create the new
thread.
 Error handling:
• #include <errno.h>
• Error handling code
Joining a Thread

Waiting for a thread


int pthread_join(pthread_t aThread, void **statusp);
‘statusp’ get return value of pthread_exit
Joining a Thread
Cannot join with a detached thread
Can only join with thread’s in the same
process address space
Multiple threads can join with one
thread but only one returns
successfully; others return with an error
that no thread could be found with the
given TID
Terminating a Thread
Main thread terminates
Thread returns
void pthread_exit(void *valuep)
Returns value pointed to by ‘valuep’
to a joining thread, provided the
exiting thread is not detached
Example 1
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/* Prototype for a function to be passed to our thread */
void* MyThreadFunc(void *arg);
int main()
{
pthread_t aThread;
/* Create a thread and have it run the MyThreadFunction */
pthread_create(&aThread, NULL, MyThreadFunc, NULL);
/* Parent waits for the aThread thread to exit */
pthread_join(aThread, NULL);
printf ("Exiting the main function.\n");
return 0; }
Example 1
void* MyThreadFunc(void* arg)
{
printf ("Hello, world! ... The threaded version.\n");
return NULL;
}

$ gcc hello.c –o hello –lpthread –D_REENTRANT


$ hello
Hello, world! ... The threaded version.
Exiting the main function.
$
Example 2
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5

void *PrintHello(void *threadid)


{
printf("\n%d: Hello World!\n", threadid);
pthread_exit(NULL);
}
Example 2
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc, t;

for (t=0; t < NUM_THREADS; t++) {


printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) {
printf("ERROR; return code is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL); }
• When this program begins, a single thread of control
begins in main().
• After some initialization, main() creates a second
thread that begins control in the runner() function.
Both threads share the global data sum.
• The statement pthread_t tid declares the identifier for
the thread we will create.
• Each thread has a set of attributes, including stack size
and scheduling information. The pthread attr_t attr
declaration represents the attributes for the thread.
We set the attributes in the function call
pthread_attr_init(&attr).
• A separate thread is created with the pthread create()
function call. In addition to passing the thread
identifier and the attributes for the thread, we also
pass the name of the function where the new thread
will begin execution—in this case, the runner()
function.
• Last, we pass the integer parameter that was provided
on the command line, argv[1].
• The program has two threads: the initial (or parent)
thread in main() and the summation (or child) thread
performing the summation operation in the runner()
function.
Windows Threads
 The technique for creating threads using the Windows thread library is
similar to the Pthreads technique in several ways.
 Threads are created in the Windows API using the CreateThread()
function, and—just as in Pthreads—a set of attributes for the thread is
passed to this function. These attributes include security information,
the size of the stack, and a flag that can be set to indicate if the thread
is to start in a suspended state.
 In situations that require waiting for multiple threads to complete, the
WaitForMultipleObjects() function is used. This function is passed four
parameters:
1. The number of objects to wait for
2. Apointer to the array of objects
3. Aflag indicating whether all objects have been signaled
4. A timeout duration (or INFINITE)
Java Threads
 Threads are the fundamental model of program execution in a Java program, and the Java
language and its API provide a rich set of features for the creation and management of
threads.
 All Java programs comprise at least a single thread of control—even a simple Java program
consisting of only a main() method runs as a single thread in the JVM.
 Java threads are available on any system that provides a JVM including Windows, Linux,
and macOS.
 The Java thread API is available for Android applications as well.
 There are two techniques for explicitly creating threads in a Java program.
One approach is to create a new class that is derived from the Thread class and to
override its run() method.
An alternative—and more commonly used—technique is to define a class that
implements the Runnable interface. This interface defines a single abstract method
with the signature public void run().
Reference & Reading Material
• “Operating Systems Concepts”,
Chapter 4 “Threads & Concurrency”, section 4.4

20
End of

Lecture # 15

You might also like