Hi everybody, I'm trying to understand pthread condition variables. For doing so, I wrote a very basic program but, no matter how many manuals and explanations I read, I just cannot understand how things work.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
#include <iostream>
#include <pthread.h>
using namespace std;
#define NT 3
#define ITERATIONS 5
int countDone=0;
int a[NT] = {10, 20, 30};
pthread_cond_t doneCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t mainCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t doneMutex = PTHREAD_MUTEX_INITIALIZER;
void * thread_start(void* num){
int currIt=0;
while(currIt < ITERATIONS){
cout << pthread_self() << " my number is " << a[(int)num] << endl;
a[(int)num]++;
pthread_mutex_lock(&doneMutex);
countDone++;
if(countDone == NT){ //everybody has done its job...
pthread_cond_signal(&doneCond); //...and I tell that to the main thread
}
while(countDone != 0){ //I wait for the main telling me to go
pthread_cond_wait(&mainCond, &doneMutex);
}
pthread_mutex_unlock(&doneMutex);
currIt++;
}
pthread_exit(NULL);
}
int main(){
pthread_t tidVec[NT];
int i, currIt=0, ret;
//creating threads
for(i=0; i<NT; i++)
pthread_create(&tidVec[i], NULL, &thread_start, (void*)i);
while(currIt < ITERATIONS){
cout << "---Iteration " << currIt << endl;
pthread_mutex_lock(&doneMutex);
while(countDone < NT){
pthread_cond_wait(&doneCond, &doneMutex);
}
countDone = 0;
pthread_cond_broadcast(&mainCond);
pthread_mutex_unlock(&doneMutex);
currIt++;
}
//waiting for threads termination
for(i=0; i<NT; i++)
pthread_join(tidVec[i], (void**)&ret);
pthread_cond_destroy(&doneCond);
pthread_mutex_destroy(&doneMutex);
return 0;
}
|
What I want it to do is: at each iteration, every thread prints the number assigned to itself in the array a, increments the value and then increments the counter countDone (which counts how many threads have already done their job). The last thread that finishes its job "tells" the main the they all are done. The main sets the counter to zero, so that a new iteration can begin. And so on for 5 iterations.
And well, it gets stuck somewhere.
What I think I understand, is that if thread A locks the mutex after the broadcast and then re-acquires it and increments countDone before threads B and C can verify the condition "while(countDone != 0)" there is a problem.
What I don't understand is how could I avoid the problem.
I hope I made myself clear enough.
Thank you for your time!