我在编写这段 C 代码时遇到了问题,因为我需要让两个生产者拥有自己的缓冲区。然后是一个消费者,它从任一缓冲区中消费一个项目,并且仅在两个缓冲区都为空时才等待。如果任一生产者缓冲区为空,消费者等待,我知道如何编写代码,
sem_wait(Xfull);
item1 = BufferX[outX];
sem_signal(Xempty);
sem_wait(Yfull);
item2 = BufferB[outY];
sem_signal(BufferBEmpty);
但我坚持这一点。
最佳答案
你可以有一个信号量来计算两个队列中未消费项目的总数。生产者向它发布消息,消费者等待它。一旦消费者成功等待信号量,它就会使用互斥体检查每个队列以找到要消费的项目。
sem_t ProducedItems; // counts total # of unconsumed items in Q's A and B
sem_t Q_A; // mutex on Q A
sem_t Q_B; // mutex on Q B
void *consumer(void *arg)
{
int bias = 0; // NOTE: could use to not always favor reading from Q A over Q B
while (1)
{
// wait for an item to be produced
sem_wait(&ProducedItems);
// find an item to consume
do
{
sem_wait(&Q_A);
{
if (Q A not empty)
{
remove an item from Q A;
bias = 1;
}
}
sem_post(&Q_A);
if (got item from A)
break;
sem_wait(&Q_B);
{
remove an item from Q B;
bias = 0;
}
sem_post(&Q_B);
}
while (0);
// consume item
}
return NULL;
}
如果消费者还需要向生产者发回信号,例如,确保他们的 Q 不会变得太大,那么您还可以为每个生产者设置信号量,指示他们的 Q 中还剩多少空间。生产者会等待它的信号量,消费者会在他们从各自的 Q 中删除项目时向它发送消息。
如果您想将此推广到 N 个生产 Q,那么您可能想要保留一个位掩码,由互斥锁保护,它指示哪些 Q 上有未使用的项目。
一旦消费者获得 ProducedItems 信号量,它就会锁定掩码以查看哪些 Q 上有未消费的项目,并对它们进行循环进程以决定下一步应该从哪个 Q 读取。然后它将锁定+从该 Q 中获取一个项目,如果该 Q 变空则更新位掩码,释放互斥锁并最终消耗该项目。
生产者会将项目放入他们的 Q 中,如果它是空的,那么他们也会锁定全局位掩码并将其 Q 的位设置在那里,释放互斥锁,然后发布 ProducedItems 信号量。
或者您可以拥有 Q 大小的数组而不是位掩码,尽管这将要求生产者在每次生产时锁定互斥锁,等等。
关于c - 一个消费者和两个生产者中的任何一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29240035/