Reputation: 2026
I am trying to implement a slightly modified version of Consumer/Producer program with a code i I picked on the internet. It is as follows with my own modifications:
/*
* Solution to Producer Consumer Problem
* Using Ptheads, a mutex and condition variables
* From Tanenbaum, Modern Operating Systems, 3rd Ed.
*/
/*
In this version the buffer is a single number.
The producer is putting numbers into the shared buffer
(in this case sequentially)
And the consumer is taking them out.
If the buffer contains zero, that indicates that the buffer is empty.
Any other value is valid.
*/
#include <stdio.h>
#include <pthread.h>
#define MAX 3 /* # of item to produce */
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
int consumeTimes[MAX] = { 1, 4, 3 };
int toConsume = 0;
void* producer(void *ptr) {
int i;
for (i = 0; i < MAX; i++) {
pthread_mutex_lock(&the_mutex); /* protect buffer */
/*while (buffer != 0) /* If there is something in the buffer then wait
pthread_cond_wait(&condp, &the_mutex);*/
printf("Producer: Produced item %d \n", i);
toConsume++;
pthread_cond_signal(&condc); /* wake up consumer */
pthread_mutex_unlock(&the_mutex); /* release the buffer */
sleep(3);
}
pthread_exit(0);
}
void* consumer(void *ptr) {
int i;
for (i = 0; i < MAX; i++) {
pthread_mutex_lock(&the_mutex); /* protect buffer */
while (toConsume <= 0) /* If there is nothing in the buffer then wait */
pthread_cond_wait(&condc, &the_mutex);
sleep(consumeTimes[i]);
printf("Consumer: Consumed item %d\n", i);
toConsume--;
//pthread_cond_signal(&condp); /* wake up consumer */
pthread_mutex_unlock(&the_mutex); /* release the buffer */
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
// Initialize the mutex and condition variables
/* What's the NULL for ??? */
pthread_mutex_init(&the_mutex, NULL);
pthread_cond_init(&condc, NULL); /* Initialize consumer condition variable */
pthread_cond_init(&condp, NULL); /* Initialize producer condition variable */
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
// Wait for the threads to finish
// Otherwise main might run to the end
// and kill the entire process when it exits.
pthread_join(&con, NULL);
pthread_join(&pro, NULL);
// Cleanup -- would happen automatically at end of program
pthread_mutex_destroy(&the_mutex); /* Free up the_mutex */
pthread_cond_destroy(&condc); /* Free up consumer condition variable */
pthread_cond_destroy(&condp); /* Free up producer condition variable */
}
Here's what I want to do:
Basically, each item has a consume and a production time.
The consume times are indicated for each item in the consumeTimes array.
So, for example consumeTimes[0] = 1 which means that consuming the 1st item should take only a single time unit.
For production, I use a constant time value, sleep(3), so producing every item should take 3 time units.
When I run the code, I get the following output all the time:
Producer: Produced item 0
Consumer: Consumed item 0
Producer: Produced item 1
Consumer: Consumed item 1
Producer: Produced item 2
Consumer: Consumed item 2
However, considering the production and consume times it should be like this:
Producer: Produced item 0 (t=0)
Consumer: Consumed item 0 (t=1)
Producer: Produced item 1 (t=3)
Producer: Produced item 2 (t=6)
Consumer: Consumed item 1 (t=7)
Consumer: Consumed item 2 (t=9)
In short, producer must always produce a new item in every 3 time intervals. But in this case, it seems to be waiting on the consumer to finish and I can't seem to figure out why.
Upvotes: 1
Views: 16415
Reputation: 70893
The consumer holds the mutex for the whole time waiting and with this does not allow the producer to run.
Change the consuming loop as follows
pthread_mutex_lock(&the_mutex); /* protect buffer */
while (toConsume <= 0) /* If there is nothing in the buffer then wait */
pthread_cond_wait(&condc, &the_mutex);
pthread_mutex_unlock(&the_mutex); /* release the buffer */
sleep(consumeTimes[i]);
pthread_mutex_lock(&the_mutex); /* protect buffer */
printf("Consumer: Consumed item %d\n", i);
toConsume--;
pthread_mutex_unlock(&the_mutex); /* release the buffer */
and you'll receive the expected result.
Upvotes: 2