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