Home > OS >  Adding to a global variable in a multi-threaded context (pthreads in C): Is my result normal? Can it
Adding to a global variable in a multi-threaded context (pthreads in C): Is my result normal? Can it

Time:01-06

So i have this program that makes 2 threads and one of those adds 5 to the global variable number while the other substracts 5

int number = 0;
bool flag = true;
pthread_mutex_t mutex;

void* change_number(void *x) {
    int num = *(int *)x;
    if(flag) {
        flag = false;
        printf("hi from thread 1\n");
        time_t now = time(NULL);
        while(now   1 > time(NULL)) {
            pthread_mutex_lock(&mutex);
            number  = num;
            pthread_mutex_unlock(&mutex);
        }
    }
    else
    {
        printf("hi from thread 2\n");
        time_t now2 = time(NULL);
        while(now2   1 > time(NULL)) {
            pthread_mutex_lock(&mutex);
            number  = num;
            pthread_mutex_unlock(&mutex);
        }

    }
}

int main(int argc, char* argv[])
{
    int id = fork();

    if(id==0) {
        int par1 = 5;
        int par2 = -5; //-(rand() % 11);
        pthread_t t1;
        pthread_t t2;
        pthread_mutex_init(&mutex, NULL);
        printf("1) SUccess code: %d\n", pthread_create(&t1, NULL, change_number, (void *) &par1));
        printf("2) Success code: %d\n", pthread_create(&t2, NULL, change_number, (void *) &par2));
        pthread_join(t1, NULL);
        printf("thread 1 finished\n");
        pthread_join(t2, NULL);
        printf("thread 2 finished\n");
        printf("Final number is: %d\n", number);
    }
    pthread_mutex_destroy(&mutex);
    wait();
    return 0;
}

Judging from the prints, i think it runs as intended but the results are very inconsistent (also i would expect the number to be close zero since they add/substract the same value). Here are some outputs:

Final number is: 8272054

Final number is: -253453

Final number is: 3405063

Am i doing something wrong? Or the output depends on the specifics of my OS?

CodePudding user response:

The biggest source of inconsistency in your results is the number of times you let each thread add/subtract to/from the global value. The now 1 > time(NULL) style doesn't guarantee at all that both the threads would execute their respective loops for the same number of times since the threads being scheduled to execute their loops is independent from the progression of system time. Either of the threads might thus lose out on its shot at executing the loop. To make this more consistent and yield the expected 0, you could perhaps have something like

    int count = 5000; // or whatever number you choose
    while(count--) {
        pthread_mutex_lock(&mutex);
        number  = num;
        pthread_mutex_unlock(&mutex);
    }

This ensures that the threads perform the operations an equal number of times irrespective of scheduling concerns and system time.

NOTE: There is a subtle bug in your program. It might so happen that both the threads handlers are executed at the same time and both see the value of flag as true and end up in the hi from thread 1 block. Of course, the value at the end would still be 0 since one is adding 5 and another -5 but this is probably not something you'd want. Try looking at other constructs (e.g. atomic_bool etc.)

A nitpick: Try having the call to wait(NULL) in the parent process rather than calling it from both the child and parent. The call from the child process would anyway exit with an error.

  •  Tags:  
  • Related