Table of Contents

Lab06 - Multi-thread programming

The goal is to implement a program with three threads running simultaneously, where the first thread is devoted for processing input (reading pressed keys), the second thread is dedicated for updating output (single line output), the third thread implements an timer, which increments a variable after a given period, which can be controlled by the user input. In this case, pthread (POSIX threads) library is used. To do that, implement simple blocks demonstrating usage of pthread library.

First threads

   void* thread1(void*);
   void* thread2(void*);

   void* thread1(void *v)
   { 
      bool q = false;  /* from the <stdbool.h> */
      while (!q) {
         usleep(100 * 1000);  /* from the <unistd.h> */
         counter += 1;
      }
      return 0;
   }

   void* thread2(void *v) 
   {
      bool q = false;
      while (!q) {
         printf(*"\rCounter %10i", counter);
      }
      return 0;
   }

   counter = 0;
 
   pthread_t thrs[2];
   pthread_create(&thrs[0], NULL, thread1, NULL);
   pthread_create(&thrs[1], NULL, thread2, NULL);

Once the thread is created, it is started and it goes to the passed function, which executed immediately.
 

   getchar();
   for (int i = 0; i < 2; ++i) {
      pthread_join(thrs[i], NULL);
   }

Use mutex for protecting critical section

In general, whenever we access to shared variable from multiple threads it is desirable to protect the access by a critical section, a lock that will allow only a single thread to accessing to the section. This can be implemented using mutex, i.e., pthread_mutex_t.

   pthread_mutex_t mtx;
   pthread_mutex_init(&mtx, NULL);

   void *thread1(void *v)
   {
      ...
      pthread_mutex_lock(&mtx);
      counter += 1;
      pthread_mutex_unlock(&mtx);
      ...
   }   

   bool quit = false;
   ...
   gechar();
   pthread_mutex_lock(&mtx);
   quit = true;
   pthread_mutex_unlock(&mtx);
   ...

   void* thread1(void *v)
   {
      ...
      while (!q) {
      ...
      pthread_mutex_lock(&mtx);
      ...
      q = quit;
      ....

Use conditional variable to signal other threads

The current implementation of the printing loop in thread2 is computationally intensive as it is executed as fast as possible using all the available cpu resources. This is not efficient and we would like to update the line only when the variable is changed. Such a synchronization mechanism can be implemented by using conditional variable, the type pthread_cond_t, “suspend” use the execution of a thread by calling pthread_cond_wait() and signal the “suspended” thread by signaling it using pthread_cond_singnal() or pthread_cond_broadcast().

    pthread_cond_t condvar;
    ...
    pthread_cond_init(&condvar, NULL);

   void* thread2(void *d)
   {
      ...
      pthread_mutex_lock(&mtx);
      ...
      pthread_cond_wait(&condvar, &mtx);
      ...
      pthread_mutex_unlock(&mtx);
      ...

   void* thread1(void *d)
   {
      ...
      pthread_mutex_lock(&mtx);
      counter += 1;
      ...
      pthread_cond_signal(&condvar);
      ...
      pthread_mutex_unlock(&mtx);
      ...

Exercise