Answers/Solutions to Exercises in Chapter 11, Exercise 5
E5: Write a simple multithreaded C program in which one
thread creates a dynamic object and a different thread deallocates it. What
kind of "communication" must take place?
S5: The sample program below is a modification of the sample program form the book. The communication that must take place is very simple --- who is the creator and who is the destroyer. The creator is the first thread that gets to it, the destroyer is the other thread. Hence, all what must be "communicated" is who was the creator and we make it a part of the OBJECT. Note the Makefile below for compiling the multihreaded porgram under UNIX and how to compile the multithread version of the logging functions. Why do we need to protect as a critical section the allocation of memory to p? If thread T1 after checking the value of p being 0 is interrupted just before the allocation by thread T2 that checks the value of p, finds it still 0, and hence allocates some memory to p. When T1 is back, it finishes its task, allocates some meory to p .... and we have memory leaking as the allocation by T2 is "forgotten" (orphaned). Why do we need to protect as a critical section the deallocation of p? If the thread T1 doing the deallocation is interrupted after the deallocation but before seting p=0, some other thread T2 might try to "work" with this non-null p, crashing the program.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include "log.h" //variables for indexing of messages by logging functions int logindex=0; int *logi = &logindex; //thread mutex lock for access to the log pthread_mutex_t tlock = PTHREAD_MUTEX_INITIALIZER; //thread mutex lock for critical sections pthread_mutex_t tlock1 = PTHREAD_MUTEX_INITIALIZER; void* doit(void*); pthread_t tid1, tid2; struct OBJECT_STRUCT { pthread_t creator; }; typedef struct OBJECT_STRUCT OBJECT; OBJECT* p=0; // function main ------------------------------------------------- int main() { create_log("log.txt"); Msg("going to create the first thread"); pthread_create(&tid1,NULL,doit,NULL); Msg("going to create the second thread"); pthread_create(&tid2,NULL,doit,NULL); Msg("going to wait for the first thread to exit"); pthread_join(tid1,NULL); Msg("the first thread exited"); Msg("going to wait for the second thread to exit"); pthread_join(tid2,NULL); Msg("the second thread exited"); exit(0); }//end main // function doit -------------------------------------------------- void* doit(void* x) { pthread_t me; me = pthread_self(); Msg("I am thread %u (p=%u)",me,p); pthread_mutex_lock(&tlock1); // critical section starts if (p==0) { p = (OBJECT*) malloc(sizeof(OBJECT)); p->creator=me; } pthread_mutex_unlock(&tlock1); // critical section ends if (p!=NULL && p->creator==me) Msg("I am thread %u and I created the OBJECT %u",me,p); else Msg("I am thread %u and I can access the OBJECT %u",me,p); pthread_mutex_lock(&tlock1); // critical section starts if (p!=NULL && p->creator==me) Msg("I am thread %u and I left the OBJECT untouched",me); else{ Msg("I am thread %u and I deleted the OBJECT",me); free((void*)p); p = NULL; } pthread_mutex_unlock(&tlock1); // critical section ends pthread_exit(NULL); return NULL; }//end doit
The Makefile:
x: x.o log.o c++ -o x x.o log.o -lpthread x.o: x.c log.h log.c c++ -D_multihtread -c x.c log.o: log.h log.c c++ -c -D_multithread log.c
The output in the log:
message number = 0, process id = 3418, time and date = 00:28:01 05/08/04 going to create the first thread message number = 1, process id = 3418, time and date = 00:28:01 05/08/04 going to create the second thread message number = 2, process id = 3418, time and date = 00:28:01 05/08/04 going to wait for the first thread to exit message number = 3, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 4 (p=0) message number = 4, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 4 and I created the OBJECT 156736 message number = 5, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 4 and I left the OBJECT untouched message number = 6, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 5 (p=156736) message number = 7, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 5 and I can access the OBJECT 156736 message number = 8, process id = 3418, time and date = 00:28:01 05/08/04 I am thread 5 and I deleted the OBJECT message number = 9, process id = 3418, time and date = 00:28:01 05/08/04 the first thread exited message number = 10, process id = 3418, time and date = 00:28:01 05/08/04 going to wait for the second thread to exit message number = 11, process id = 3418, time and date = 00:28:01 05/08/04 the second thread exited
Back to Answers/Solutions Index Back to Answers/Solutions for Chapter 11 Index