一个生产者和多个消费者:如果有N个消费者和N个类型的产品,我应该使用N个信号量吗?

时间:2013-05-14 17:30:21

标签: c multithreading algorithm mutex semaphore

我有一个包含1个生产者线程和N个消费者线程的程序。有N种类型的产品,所以我设置了N个FIFO队列(产品应按顺序交付给消费者)。如:FIFO_queue_t * fifo_queque [N]。

如果FIFO队列中没有产品,则阻塞/等待使用者线程。 因此,对于消费者线程i,他们会这样做:

        for(;;)
        {
            sem_wait(&sem[i]);
            product = fetch_one_product(queue);
            process(product);
         }

对于生产者,当它将线程i的产品放入FIFO队列i时,它会调用sem_post(& semp [i])。

在我看来,在这种情况下我必须使用N个信号量,如果N很大,则资源消耗很大。我的想法中有什么遗漏?

更新

 The system is like a proxy, and my original design is like this:

我有一个tcp服务器正在侦听端口listen(listenfd, 20);

生产者是一个libpcap实例,它从该端口捕获TCP数据包,产品是捕获数据包(包括IP / TCP头);

对于每个connfd = accept(listenfd)。我创建了一个负责此connfd的线程。这些线程是消费者。

我创建了一个查找表,每个条目中的字段是:

1 source IP/PORT, source address of incoming TCP connection,
2 FIFO Queue pointer: the fifo queue of captured spacket
3 pthread id :  the thread that is responsible for a tcp connection

当生产者线程获取数据包时,它会从数据包中解析源IP / PORT,查找表,找到FIFO队列并将其放入FIFO队列。

当消费者线程收到通知,其FIFO队列中有一些数据包时,它会从队列中获取数据包。特别是,对于初始3路数据包:TCP SYN,SYN / ACK和ACK,它需要维护一些状态信息,如MSS,SACK等。 它还需要将这些数据包(包括TCP / IP头)作为UDP有效负载,并将UDP数据包发送到其他一些远程主机。

1 个答案:

答案 0 :(得分:1)

这似乎是一种不能很好地扩展的设计。如果您有1,000种不同的产品,那么您将拥有1,000个不同的FIFO队列,1,000个信号量和1,000个线程。这几乎是不可能管理的。

使用单个队列和少量线程会更好。线程可以处理任何类型的项目。您唯一的困难是按顺序向客户交付物品,但通常不会成为问题。要解决这个问题,您需要做的就是添加某种序列号,以便在项目即将发送给客户时,检查序列号并等待它不是您期望的序列号。

当然,您实际上并没有等待,而是将项目放入被阻止的输出队列中,等待正确的项目进入。如果您可以保证线程不会崩溃,那么这很有效。丢弃一个项目。因为如果发生这种情况,输出到您的客户将停止。你需要一些可以阻止永久阻止的策略:可能是一个超时,说:“好吧,我等了很长时间。即使它出现故障,客户也会得到这个项目。”

在回复评论时添加:

所以你有一个由生产者填充的单个输入队列,少量的消费者线程,每个线程都可以处理任何类型的产品,然后是N个输出队列(看起来过多),或者是单个输出队列溢出以允许缓冲无序项目。我假设您有少量线程(可能只有一个?)为输出队列提供服务并将项目发送给客户。

不按规定的物品应该只在非常短的时间内停留在溢流口。他们在那里因为两个(或更多)相同类型的物品非常接近地出列,后者在前一个物品之前完成处理。这应该是一个罕见的事件,所以你的溢出桶应该不是很大。您可以轻松地将溢出设置为一个简单的列表,并按顺序扫描它,而不会有明显的性能损失。