gpt4 book ai didi

C - 当生产者大于缓冲区大小时,消费者/生产者出现死锁

转载 作者:太空宇宙 更新时间:2023-11-04 03:02:27 26 4
gpt4 key购买 nike

我的任务是使用线程和信号量来解决生产者和消费者问题。任务是允许用户定义生产者数量、消费者数量和缓冲区大小。如果生产者达到缓冲区大小,程序将始终锁定。但是要求说如果生产者达到 buffersiz 消费者线程应该启动并从缓冲区中获取东西。我不知道如何解决这个问题,我的老师拒绝提供帮助。我完全是C语言的初学者,请给我一些建议。非常感谢

我的程序可以在 Producer = Consumer 或 Producer < Consumer, except Producer > Buffer Size 时运行,似乎出现了死锁,我想我明白了原因,但我不知道如何修复代码让消费者线程先运行,然后返回生产者线程。

这里是producer=3,consumer=1,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

要求说结果应该是这样的

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 作为变量来显示缓冲区内剩余的项目,但这是错误的。使用其他变量,如 front 或 rear 也不起作用。

程序结果-

生产者=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!

最佳答案

您的缓冲区大小为 2。前 2 个生产者填满此缓冲区。因此,第三个正在等待消费者拿走一件元素,以便它可以添加到缓冲区。 但是生产者循环中的 pthread_join 根本不允许创建消费者! pthread_join 正在暂停 main 进程直到第三个生产者终止。因此,第三个生产者无限期地等待缓冲区被从未到达的消费者释放的死锁。

我建议你通过Exercise 3这篇文章的一部分处理与您完全相同的问题和相同的数据结构。他们已经清楚地阐明了如何防止缓冲区溢出,在哪里打印生产者数据。可能是针对毕业生的标准信号量教程练习。

关于C - 当生产者大于缓冲区大小时,消费者/生产者出现死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9887170/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com