I’m trying to implement producer-consumer model and I got some problem with it. Consider code
int number=0;
void* master(void* p){
int i;
pthread_t workers[5];
for(i=0;i<5;i++)
pthread_create(&workers[i],NULL,worker,NULL);
while(1){
//possible delay
pthread_mutex_lock(&mutex);
if(number == LIMIT)
pthread_cond_wait(¬_full,&mutex);
number++;
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&mutex);
}
}
void* worker(void* p){
while(1){
pthread_mutex_lock(&mutex);
if(number == 0)
pthread_cond_wait(¬_empty,&mutex);
number--;
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&mutex);
//possible delay
}
}
Maybe it’s obvious to you, but I can’t figure out how is it possible that the variable number get’s negative which of course lets the worker thread decrement it further. What am I doing wrong?
–EDIT–
Ok one progress is doing while(number==0) instead of if, yet I still don’t understand how could it happen that there could be two threads decrementing the variable after getting the not_empty signal while it is less then two.
I think replacing if with while may be masking a problem rather than solving it. Per Why do pthreads’ condition variable functions require a mutex? the mutex you use with a condition variable is used to protect access to that condition variable. In your case you appear to be using
mutexto protect three things: the globalnumber, and two condition variables,not_fullandnot_empty.Something you need to realize — the implementation of pthread_cond_wait() will unlock your mutex, and re-locked it before it returns, and this window of being open is allowing for other threads to get in when you don’t want them to. Replacing if with while as you have is one solution, but another is using a second mutex in your worker to protect access to both “number” as well as the conditioned wait.