c - 一个消费者和两个生产者中的任何一个

标签 c multithreading semaphore producer-consumer

我在编写这段 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/

相关文章:

c - 从文件中读取带空格的字符串

c - 菜单程序的 Excel 数据文件

c# - Application.Wait 或 Thread.Sleep

iphone - Objective C - 异步http请求阻塞程序

c - 为什么我的生产者消费者阻塞了?

将字符转换为 C 数组中的空格

python - 在 Python 中覆盖 threading.excepthook 的正确方法是什么?

C++ 使用信号量代替忙等待

c - 在执行 sem_timedwait 时,我将如何应对系统时间的变化?

c - Double 在递归中返回 0,但在 int 时工作正常