0

I am beginner in multi thread programming. I have a homework, which I should create some number of thread (in my case 10) and generate a random number inside of each one. when I debug my code (or put 'sleep(1)' command) it works correctly, otherwise the generated values are not equal anymore. please help me and explain me if you think there is something which I still did'nt understand it. The code:

#include<stdio.h>
#include<pthread.h>
#include<time.h>

int rn, sharedArray[10];
pthread_mutex_t lock;


int randomgenerator(){
    //sleep(1);
    srand(time(NULL)); // The value of random depend on the time with some changes in the time library
    int rn, MAX = 10; //  between 0 and 10
    rn = rand()%MAX;
    return rn;
}

void *rgen(void *arg){
    int order = (int*)arg;
    //pthread_mutex_lock(&lock);
    int rn = randomgenerator();
    printf("%d,%d\n", order,rn); //not working without printf why????
    sharedArray[order]= rn;
    //pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

void main(int argc, char *argv[]){
    pthread_mutex_init(&lock, NULL);
    pthread_t th[10];
    int i;
    for (i = 0; i <10; i ++){
        pthread_create(&(th[i]), 0, rgen, (void *)i);
        pthread_join(th[i], NULL);
    }

    int j, result = 0;
    for (j=0; j<10; j++){
        result = sharedArray[j] + result;
    }
    printf("the final result is: %d\n",result);
    pthread_exit(NULL);
    pthread_mutex_destroy(&lock);
}

And the output is:

0,3
1,3
2,3
3,3
4,3
5,3
6,3
7,3
8,3
9,3
the final result is: 30

The output which I expect with uncommenting the sleep is:

0,7
1,4
2,1
3,8
4,5
5,2
6,9
7,6
8,3
9,0
the final result is: 45
dragosht
  • 3,237
  • 2
  • 23
  • 32
Ali Payandeh
  • 63
  • 1
  • 10
  • Just at a glance I'm concerned with how you are passing your void * to the pthreads. Please see http://stackoverflow.com/questions/8487380/how-to-cast-an-integer-to-void-pointer and http://stackoverflow.com/questions/8618637/what-does-it-mean-to-convert-int-to-void-or-vice-versa for more on this. The big issue is basically you are trying to cast from an integer to a void * without even using the & operator anyways see them for "correct" ways to do it. – arduic Dec 14 '15 at 13:14
  • Also, you are launching 1 thread and calling join on that thread. This will result in only 1 thread running at a time. You should split the loop and launch all threads and than perform a join. – brano Dec 14 '15 at 13:59

1 Answers1

1

The problem is this line:

srand(time(NULL));

The man page for rand/srand says:

The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value.

You set a new seed every time. That is wrong! You should only call srand once.

When you comment out the sleep, all threads set the same seed and then gets the first random number in that sequence. If they do it in the same second, they each get the same random value.

Solution:

Move the call to srand to main, before you create any threads.

Note:

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.

That means that you cannot safely call rand simultaneously from multiple threads. You should either protect the call by using a mutex or semaphore, or switch to a reentrant function, like rand_r.

Community
  • 1
  • 1
Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82