I have assignment to work on producer and consumer problem by use thread and semaphore. The task is that allow user to define # of producer,# of consumer and buffer size. The program always lock if producer reach the buffersize. But the requirement says if producer reach buffersiz the consumer thread should start and take things from buffer. I am out of idea how to fix this problem and my teacher refuse to help. I am a totally beginner of the C language, please give me some suggestion. Thank you very much
My program can run when Producer = Consumer, or Producer < Consumer, except Producer > Buffer Size, it seems to appear deadlock, and I think I understand the reason why but I don’t know how to fix the code to let Consumer thread run first than back to Producer thread.
Here is the running result when producer =3 consumer = 1 and buffersize = 2
./Task2 3 1 2
Producer 0 has started
Producer 0:Put item 0.
Producer 1 has started
Producer 1:Put item 1.
Producer 2 has started
The requirement says the result should looks like
Started
Producer 0 has started
Producer 0: Put item 0.
Producer 1 has started
Producer 1: Put item 1.
Producer 2 has started
Consumer 0 has started
Consumer 0: Taked item 0.
Producer 2: Put item 2.
Terminated!
Here is my origional code, I have discard some input error check code
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
pthread_t *pid, *cid;
void *producer(void *param);
void *consumer(void *param);
void init();
int Remove();
struct prot_buffer{
int Producer;
int Consumer;
int *buffer;
int buffersize;
int front;
int rear;
int item;
sem_t mutex;
sem_t slots;
sem_t items;
}b;
main(int argc, char *argv[]){
int c1;
b.Producer = atoi(argv[1]);
b.Consumer = atoi(argv[2]);
b.buffersize = atoi(argv[3]);
init();
pid = (pthread_t *)malloc(b.Producer *sizeof(pthread_t));
cid = (pthread_t *)malloc(b.Consumer *sizeof(pthread_t));
for (c1=0; c1< b.Producer; c1++){
printf("Producer %d has started\n", c1);
pthread_create(&(pid[c1]),NULL, producer, NULL);
pthread_join(pid[c1], NULL);
printf("Producer %d:Create item %d.\n", c1,c1);
}
/* Create the consumer threads */
for (c1=0; c1<b.Consumer; c1++){
printf("Consumer %d has started\n", c1);
pthread_create(&(cid[c1]),NULL, consumer, NULL);
if (b.front==b.rear){
printf("Terminated!\n");
exit(0);
}
pthread_join(cid[c1], NULL);
printf("Consumer %d:Taked item %d.\n", c1, c1);
}
free(b.buffer);
free(pid);
free(cid);
sem_destroy(&b.items);
sem_destroy(&b.slots);
sem_destroy(&b.mutex);
printf("Threads terminated!\n");
exit(0);
}
void *producer(void *param){
sem_wait(&b.slots); sem_wait(&b.mutex);
if(b.rear<=b.buffersize){
b.buffer[b.rear] = b.item;
b.rear++;
sem_post(&b.mutex); sem_post(&b.items);
}else{
sem_post(&b.mutex); sem_post(&b.items); }
}
void *consumer(void *param){
Remove();
}
void init(){
b.buffer = (int *) malloc(b.buffersize *sizeof(int));
b.buffersize = b.buffersize;
b.front = b.rear =0;
sem_init(&b.items, 0, 0);
sem_init(&b.slots,0,b.buffersize);
sem_init(&b.mutex, 0, 1);
}
int Remove(){
sem_wait(&b.items);
sem_wait(&b.mutex);
b.item = b.buffer[b.front];
b.front++;
sem_post(&b.mutex);
sem_post(&b.slots);
return b.item;
}
My new code
main(int argc, char *argv[]){
...
pthread_create(&pid,NULL, producer, NULL);
pthread_create(&cid,NULL, consumer, NULL);
....
}
void *producer(void *param){
int c2;
for (c2=0; c2 < b.Producer; c2++) {
printf("Producer %d has started\n", c2);
b.item = c2;
sem_wait(&b.slots);
sem_wait(&b.mutex);
b.buffer[b.rear] = b.item;
b.rear = (b.rear+1)%b.buffersize;
printf("Producer %d:Put item %d.\n", c2,c2);
sem_post(&b.mutex);
sem_post(&b.items);
}
return NULL;
}
void *consumer(void *param){
int c2;
for (c2=0; c2 < b.Consumer; c2++) {
printf("Consumer %d has started\n", c2,c2);
b.item = c2;
sem_wait(&b.items);
sem_wait(&b.mutex);
b.buffer[b.front] = b.item;
b.front = (b.front+1)%b.buffersize;
printf("Consumer %d:take item %d.\n", c2, c2);
sem_post(&b.mutex);
sem_post(&b.slots);
}
return NULL;
}
To avoid trobule at school I remove some code and some description.
The program result is correct now, thanks for help. In this case I use b.item as the variable to display the item left inside the buffer, but its wrong. Use other variable like front or rear also not work too.
Program result-
Producer=2, Consumer=2, Buffer=2
./F 2 2 2
started
Producer 0 has started
Producer 0:Put item 0.
Producer 1 has started
Producer 1:Put item 1.
Consumer 0 has started
Consumer 0:Take item 0.
Consumer 1 has started
Consumer 1:Take item 1.
1 item(s) left in the buffer! //This is wrong!
Terminated!
Producer=3, Consumer=1, Buffer=2
./F 3 1 2
started
Producer 0 has started
Producer 0:Deposited item 0.
Producer 1 has started
Producer 1:Deposited item 1.
Producer 2 has started
Consumer 0 has started
Consumer 0:Removed item 0.
Producer 2:Deposited item 2.
0 item(s) left in the buffer! //Still wrong!
Terminated!
Producer =2, Consumer = 5, Buffer =3
./F 2 5 3
started
Producer 0 has started
Producer 0:Put item 0.
Producer 1 has started
Producer 1:Put item 1.
Consumer 0 has started
Consumer 0:Take item 0.
Consumer 1 has started
Consumer 1:Take item 1.
Consumer 2 has started
2 item(s) left in the buffer! //Wrong again!
Terminated!
Your buffer size is 2. The first 2 producers fill up this buffer. Hence the third one is waiting for a consumer to take one item so that it can add to buffer. But your
pthread_joininside the producer loop never allows for consumers to be created at all!pthread_joinis suspendingmainprocess until 3rd producer terminates. Hence the deadlock where in the third Producer is indefinitely waiting for the buffer to be freed by a consumer who never arrives.I suggest you go through Exercise 3 of this article which deals with exactly the same problem and the same data structure as yours. They’ve clearly articulated how to prevent buffer overflow, where to print producer data. May be its a standard semaphore tutorial exercise for grads.