essence16
essence16

Reputation: 173

Simple C++ pthread program output don't match with expectation

I am currently learning operating systems and I am running the following code:

#include<iostream>
#include<pthread.h>
using namespace std;
#define Num_Threads 4

void *hello (void *arg){
    int* p = (int *)arg; 
    cout << *p << endl;
    return 0;
}

int main(){
    int i = 0;
    pthread_t tid[Num_Threads];
    for (i = 0; i < Num_Threads; i++){
        pthread_create(&tid[i], nullptr, hello, &i);
    }
    for (i = 0; i < Num_Threads; i++){
        pthread_join(tid[i], nullptr);
    }
    return 0;
}

I use the following compiling commands in MaxOS:

 g++ pThead.cpp -pthread -o test
 ./test 

I am expecting this program to randomly output permutation of 0, 1, 2, 3 but it usually have some outputs like 3,0,0,0; 3,1,0,0 etc. I am a beginner to multithread so this question may look naive but I am grateful if someone can answer it.

Upvotes: 1

Views: 68

Answers (3)

Galik
Galik

Reputation: 48615

Your threads are working on a pointer to i and i changes value while the threads are running.

So you also have a race condition where you are writing to and reading from the same variable i from different threads simultaneously.

A possible solution is to create an array with an independent variable for each thread.

#include<iostream>
#include<pthread.h>
using namespace std;
#define Num_Threads 4

void *hello (void *arg){
    int* p = (int *)arg;
    cout << *p << endl;
    return 0;
}

int main(){

    pthread_t tid[Num_Threads];

    int v[Num_Threads]; // a variable for each thread

    for (int i = 0; i < Num_Threads; i++){

        v[i] = i; // set a variable unique to each thread
        pthread_create(&tid[i], nullptr, hello, &v[i]);
    }

    for (int i = 0; i < Num_Threads; i++){
        pthread_join(tid[i], nullptr);
    }
    return 0;
}

Of course std::cout is thread safe for individual calls but multiple calls can get interleaved when multiple threads are writing to it. So your std::endl may not happen exactly between each output number (probably won't) and the numbers could occur in any order.

Upvotes: 4

Nipun Talukdar
Nipun Talukdar

Reputation: 5387

This is happening because you are printing value from the same address location and when the value will be read by the spawned thread is unpredictable. If the OS is starting threads too fast, you may see the values as 0, 1,2,3 but that will be unlikely.

Upvotes: 1

Your threads are running too quickly. Probably outputting a single number takes a few dozens of microseconds only, and your system don't schedule or run threads that fast.

Try to run some routine more complex than your hello

I am expecting this program to randomly output permutation of 0, 1, 2, 3

"randomly" is not the right word. You mean "unpredictably"

      pthread_create(&tid[i], nullptr, hello, &i);

The &i is wrong: all the threads get the same address.

Either allocate on heap:

       int *p = malloc(sizeof(int));
       if (!p) { perror("malloc");  exit(EXIT_FAILURE);  };
       *p = i;
        pthread_create(&tid[i], nullptr, hello, p);

but then you have a memory leak (since you never free)

or pass the integer directly (since int fits in a word on most platforms)

        pthread_create(&tid[i], nullptr, hellodirect, (void*)(intptr_t)i);

but then you need another function

 void *hellodirect (void *arg){
    int i = (int)(intptr_t)arg; 
    cout << i << endl;
    return nullptr;
 }

Upvotes: 0

Related Questions