0

The problem with the following program is that the main thread ends before the other threads get a chance to display their results. Another issue is that the threads display isn't in order.

The output needs to be:

This is thread 0. 
This is thread 1. 
This is thread 2. etc.

code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = { 4, 6, 3, 1, 5, 0, 2 }; // Order in which to start threads
int num = 0;
int main()
{
 int i;
 pthread_t tid[7];
 // Initialize random number generator
 time_t seconds;
 time(&seconds);
 srand((unsigned int) seconds);
 // Create our threads
 for (i = 0; i < 7; i++)
 pthread_create(&tid[i], NULL, text, (void*)code[i]);
 // Exit main
 return 0;
}
void *text(void *arg)
{
 long n = (long)arg;
 int rand_sec = rand() % (3 - 1 + 1) + 1; // Random num seconds to sleep
 while (num != n) {} // Busy wait used to wait for our turn
 num++; // Let next thread go
 sleep(rand_sec); // Sleep for random amount of time
 printf("This is thread %d.\n", n);
 // Exit thread
 pthread_exit(0);
} 

Can anyone help with using a mutex to fix the synchronization problem?

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
user3434743
  • 155
  • 2
  • 9
  • Your serialization requirement is like asking for you new car to be fitted with square wheels and, anyway, a mutex is an inappropriate mechanism for even that. – Martin James Mar 06 '16 at 14:24
  • You can use barriers to synchronize all the threads which fixes the killing of threads problem. Also, there in no known method of sequential alignment of threads. It kills the purpose of threads in the first place. You need to explicitly use shared memory to signal threads for serializing the print sequence. – jada12276 Mar 06 '16 at 14:29
  • Essentially, you are killing any advantage of multi-threading you may have by applying mutex and synchronization. Normally it will be slower than its counterpart single threaded application. Regarding your second issue of exiting application before any thread finishes, you can use join to wait for all threads completion before exiting. – Saleem Mar 06 '16 at 16:10

1 Answers1

4

You can use pthread_join to make your main routine wait until your other threads have finished, e.g.

int main()
{
 int i;
 pthread_t tid[7];
 // Initialize random number generator
 time_t seconds;
 time(&seconds);
 srand((unsigned int) seconds);
 // Create our threads
 for (i = 0; i < 7; i++)
   pthread_create(&tid[i], NULL, text, (void*)code[i]);
 for(i = 0; i < 7; i++)
   pthread_join(tid[i], NULL);
 // Exit main
 return 0;
}

Also, your code which waits for num to be the thread ID might have some issues when you start turning optimisations on. Your num variable should be declared volatile if it is shared between threads, like so:

volatile int num;

That said, busy waiting on num like so is very, very inefficient. You should consider using condition variables to notify threads when num changes, so they can check if it is their turn once, then sleep if not. Have a look at all of the pthread_cond_* functions for more information.

slugonamission
  • 9,562
  • 1
  • 34
  • 41
  • 2
    [`volatile` is not for multithreading](http://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming). You should use a proper atomics datatype, like [C11 atomics](http://en.cppreference.com/w/c/atomic). – ComicSansMS Mar 06 '16 at 14:56