У меня есть задание работать над проблемой производителя и потребителя, используя поток и семафор. Задача состоит в том, чтобы позволить пользователю определить # производителя, # потребителя и размер буфера. Программа всегда блокируется, если производитель достигает размера буфера. Но в требовании говорится, что если производитель достигает размера буфера, поток потребителя должен запускаться и брать данные из буфера. Я понятия не имею, как решить эту проблему, и мой учитель отказывается помочь. Я совсем новичок в языке C, пожалуйста, дайте мне какое-нибудь предложение. Большое Вам спасибо
Моя программа может работать, когда Producer = Consumer или Producer ‹ Consumer, за исключением Producer > Buffer Size, кажется, что это тупиковая ситуация, и я думаю, что понимаю причину, но я не знаю, как исправить код, чтобы позволить потоку Consumer работать сначала, чем вернуться к потоку Producer.
Вот текущий результат, когда производитель = 3, потребитель = 1 и размер буфера = 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
Требование говорит, что результат должен выглядеть так
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!
Вот мой исходный код, я отбросил код проверки ошибок ввода
#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;
}
Мой новый код
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;
}
Чтобы избежать неприятностей в школе, я удаляю часть кода и часть описания.
Результат программы теперь правильный, спасибо за помощь. В этом случае я использую b.item как переменную для отображения элемента, оставшегося внутри буфера, но это неправильно. Использование других переменных, таких как передняя или задняя, также не работает.
Результат программы-
Производитель=2, Потребитель=2, Буфер=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!
Производитель=3, Потребитель=1, Буфер=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!
Производитель = 2, Потребитель = 5, Буфер = 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!
malloc
не требуется. - person Daniel Kamil Kozar   schedule 27.03.2012