Lab03 Multithreading
Lab03 Multithreading
In this lab we will look at multi-threading. For this task we will use POSIX pthread library.
pthread Library
pthread library is the POSIX standard for multi-threading. In this lab session we will be exploring and
exploiting its power.
int main(void)
{
pthread_t mythread;
if ( pthread_create( &mythread, NULL, thread_function, NULL) )
{
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread, NULL ) )
{
printf("error joining thread.");
abort();
}
printf("Main thread says hi!\n");
exit(0);
}
Exercise1
1. Save the above program as thread.c and compile it as:
gcc -pthread -o thread thread.c -Wall
a) Why do you need '-pthread' flag when you compile?
pthread_t type
pthread_t is of an unsigned integer type. In 64bit Linux systems, it is an unsigned long integer. The
value in pthread_t represents the thread (something similar to a pid for a process).
pthread_create() call
This function creates and runs the new thread. This takes few arguments and returns an integer. The
first argument taken is the pointer for the pthread_t type variable. The tid value is stored by this
function in this pointer.
The next argument is a struct of type pthread_attr_t which specifies the attributes that we have to
use when creating a thread. We are not going to discuss these attributes. Therefore we set this value to
NULL, allowing the attributes to be in their default values.
The next argument is the function pointer to the function that the thread should execute. This function
could take one argument of type void* and returns a value of type void* (void* is the generic type in
C that represents any type of pointer)
The last argument is the argument that should be passed to the function that the thread should
execute. This argument should be of type void*. We have set this value to NULL since we're not
passing any arguments to our function.
pthread_create() returns 0 in success and returns an non zero integer representing the error code
otherwise.
Exercise2
1. Consider the following piece of code from multiprocessing lab session:
int i;
for (i = 0; i < 3; i++)
fork();
a) how many new processes did it create?
b) how many threads will it create? Compare this with a) above. Why is there a difference?
Passing parameters to the function that the thread executes and using those within the thread function
is a bit tricky. The following example passes a count variable to the thread_function, and update its
value within the function call (Note: the Line Numbers are provided to assist you in the next exercise).
1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <stdio.h>
5
6 void *thread_function(void *arg)
7 {
8 int a;
9 for(a = 1; a <= 3; a++)
10 {
11 printf("Thread %d:%d says hi!\n", *(int *)arg, a);
12 // sleep(1);
13 }
14
15 (*(int *)arg)++;
16 return NULL;
17 }
18
19 int main(void)
20 {
21 pthread_t mythread;
22 int i, count = 1;
23
24 for (i = 0; i < 5; i++){
25 if (pthread_create( &mythread, NULL, thread_function, &count))
26 {
27 printf("error creating thread.");
28 abort();
29 }
30 if ( pthread_join ( mythread, NULL ) )
31 {
32 printf("error joining thread.");
33 abort();
34 }
35 // sleep(1);
36 }
37 // sleep(1);
38 printf("Main thread says hi!\n");
39 exit(0);
40 }
void* handle_client(void*);
int main()
{
int listenfd;
int* connfd;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
listenfd = socket(AF_INET,SOCK_STREAM,0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(32000);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
listen(listenfd,5);
clilen = sizeof(cliaddr);
while(1)
{
connfd = malloc(sizeof(int));
*connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
/* now create a new thread, pass it the socket and run the thread. */
}
}
2. Why do you need to declare connfd as a variable in the heap? What problem might occur if it
was declared as a local variable?