我正在编写一个具有多生产者、单消费者模型的应用程序(多线程将消息发送到单个文件写入器线程)。
每个生产者线程包含两个队列,一个用于写入,另一个用于消费者读取。消费者线程的每一个循环,它都会遍历每个生产者,并锁定生产者的互斥锁,交换队列,解锁,并从生产者不再使用的队列中写出。
在消费者线程的循环中,它在处理完所有生产者线程后休眠一段指定的时间。我立即注意到的一件事是,当我从1个生产者线程转移到2个生产者线程时,生产者将一些东西写入队列并返回的平均时间急剧增加(增加了5倍)。随着线程的增加,平均时间减少,直到触底- 10个生产者和15个生产者之间的时间没有太大差异。这大概是因为有了更多的生产者来处理,生产者线程的互斥争用就少了。
不幸的是,对于应用程序来说,拥有<5个生产者是相当常见的场景,我希望优化睡眠时间,这样无论存在多少生产者,我都能获得合理的性能。我注意到,通过增加睡眠时间,我可以在生产者数量较少的情况下获得更好的性能,但在生产者数量较大的情况下性能较差。
其他人遇到过这种情况吗?如果有,你的解决方案是什么?我尝试过用线程的数量来调整休眠时间,但这似乎是机器特有的,而且是反复试验的。
发布于 2009-09-09 17:02:54
您可以根据生产者的数量来选择睡眠时间,甚至可以根据一些动态方案来调整睡眠时间。如果消费者醒来时没有工作,则将睡眠时间增加一倍,否则将睡眠时间减半。但是将睡眠时间限制在某个最小值和最大值。
无论哪种方式,你都是在掩盖一个更根本的问题。睡眠和轮询很容易正确,有时是唯一可用的方法,但它有许多缺点,不是“正确”的方法。
您可以通过添加一个信号量来朝着正确的方向前进,该信号量在生产者向队列中添加项目时递增,在消费者处理队列中的项目时递减。只有当有项目需要处理时,消费者才会被唤醒,并且会立即这样做。
然而,轮询队列可能仍然是一个问题。您可以添加一个新队列,该队列引用其中包含项目的任何队列。但它提出了一个问题,即为什么没有消费者处理的单个队列,而是每个生产者都有一个队列。在其他条件相同的情况下,这听起来是最好的方法。
发布于 2009-12-03 03:25:33
而不是睡觉,我会建议你的消费者在生产者发出信号的条件下阻止。在与posix兼容的系统上,您可以使其与pthread_cond一起工作。创建一个pthread_cond_t数组,每个生产者一个,然后再创建一个在它们之间共享的数组。生产者首先发信号通知各自的条件变量,然后发信号通知共享的条件变量。使用者等待共享条件,然后迭代数组的元素,对数组的每个元素执行一次pthread_cond_timed_wait() (使用pthread_get_expiration_np()获取“现在”的绝对时间)。如果等待返回0,则该生产者已写入数据。使用者必须重新初始化条件变量,然后才能再次等待。
通过使用阻塞等待,您将最小化使用者不必要地锁定生产者的时间。您也可以使用信号量来实现这一点,正如前面的回答所述。在我看来,与条件相比,信号量简化了语义,但您必须小心地为每个生产者减少一次共享信号量,该生产者在每次通过消费者循环时被处理。条件变量的优点是,如果在发出信号后重新初始化它们,基本上可以像使用布尔信号量一样使用它们。
发布于 2009-09-09 16:34:54
尝试在您用于编程的语言中找到阻塞队列的实现。对于任意数量的生产者和一个消费者来说,不超过一个队列就足够了。
https://stackoverflow.com/questions/1400605
复制相似问题