0

I have the following code:

#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <queue> using namespace std; queue<int> myqueue; pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; void *consumer(void*); void *producer(void*); #define COUNT_DONE 10 int count = 0; main() { pthread_t thread1, thread2; pthread_create( &thread2, NULL, &consumer, NULL); pthread_create( &thread1, NULL, &producer, NULL); pthread_join( thread1, NULL); pthread_join( thread2, NULL); printf("Final count: %d\n",count); system("PAUSE"); return EXIT_SUCCESS; } void *consumer(void*) { for(;;) { // Lock mutex and then wait for signal to relase mutex printf("consumer mutex lock \n"); pthread_mutex_lock( &count_mutex ); printf("consumer mutex locked\n"); // Wait while functionCount2() operates on count // mutex unlocked if condition varialbe in functionCount2() signaled. printf("consumer wait\n"); pthread_cond_wait( &condition_var, &count_mutex ); printf("consumer condition woke up\n"); myqueue.pop();count--; printf("Counter value consumer: %d\n",count); printf("consumer mutex unlock\n"); pthread_mutex_unlock( &count_mutex ); if(count >= COUNT_DONE) return(NULL); } } void * producer(void*) { for(;;) { printf("producer mutex lock\n"); pthread_mutex_lock( &count_mutex ); printf("producer mutex locked\n"); if( count < COUNT_DONE) { myqueue.push(1); count++; printf("Counter value producer: %d\n",count); printf("producer signal\n"); pthread_cond_signal( &condition_var ); } printf("producer mutex unlock\n"); pthread_mutex_unlock( &count_mutex ); if(count >= COUNT_DONE) return(NULL); Sleep(5000); } } 

This is example works fine when consumer thread takes the mutex first. But then when the producer thread acquires the mutex initially at first, I will always have 1 integer in the queue that the consumer can't pop.

How can I let the consumer thread, initially acquire the mutex before the producer.

Note: I am looking for a better way than launching one thread before the other.

Thanks,

1 Answer 1

1

One problem I see is that your consumer doesn't actually check for work to do, it just blindly pops from the queue.

The second problem I see is that you increment count in one and decrement it in the other, so how do you ever reach the termination condition?

Take the ninja "count--" out of consumer and it should work. Still, you might want to do the following inside consumer:

// Wait for producer to do its thing and tell us there is work to do. while ( myqueue.empty() ) { pthread_cond_wait(&condition_var, &count_mutex); } // we've been told there's work to do with the queue, // and we know there's something ON the queue. // consume the entire queue. while ( !myqueue.empty() ) { myqueue.pop(); } // treat count as protected by the mutex, so hoist this test into the lock. bool workDone = (count >= COUNT_DONE); pthread_mutex_unlock(&count_mutex); if(workDone) return break; 

edit: preferred version of consumer:

bool workDone = false; while(workDone == false) { // Lock mutex and then wait for signal to relase mutex pthread_mutex_lock( &count_mutex ); // Wait for producer to do its thing and tell us there is work to do. while ( myqueue.empty() ) pthread_cond_wait( &condition_var, &count_mutex ); // we've been told there's work to do with the queue, // and we know there's something ON the queue. // consume the entire queue. while ( myqueue.empty() == false ) { myqueue.pop(); } // count is protected by the lock so check if we're done before we unlock. workDone = (count >= COUNT_DONE); pthread_mutex_unlock( &count_mutex ); } return NULL; 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.