【发布时间】:2012-02-16 22:41:02
【问题描述】:
我已经构建了一个多线程生产者-消费者(添加到队列,使用多个线程从队列中消耗),但我试图通过将新的生产()直接发送到执行线程来进一步优化,如果它们是空闲的(而不是将其排入队列)。
所以,我需要弄清楚线程当前在哪里执行(它当前是有条件地等待,还是正在执行某些事情)。谁能建议一种方法来做到这一点?
【问题讨论】:
标签: c++ multithreading pthreads producer-consumer
我已经构建了一个多线程生产者-消费者(添加到队列,使用多个线程从队列中消耗),但我试图通过将新的生产()直接发送到执行线程来进一步优化,如果它们是空闲的(而不是将其排入队列)。
所以,我需要弄清楚线程当前在哪里执行(它当前是有条件地等待,还是正在执行某些事情)。谁能建议一种方法来做到这一点?
【问题讨论】:
标签: c++ multithreading pthreads producer-consumer
如果执行线程空闲,它不会在队列中等待吗?让它完成一些工作的最快方法可能是将工作推到队列中。
你有理由相信队列是一个瓶颈吗?
【讨论】:
这就是队列应该做的。
首先,线程不能空闲,除非队列为空,对吧?
那么您的“入队和信号”操作是做什么的?它在线程可以找到数据的地方放置一个指针,然后告诉线程处理数据。无论如何,这是做你想做的事情的最低限度的任务。
所以应该不可能优化。
【讨论】:
您可以为每个线程设置一个全局标志,指示它是否正在等待。只需在进入 pthread_cont_wait 之前设置标志并在释放时将其重置。
说了这么多,我真的不明白你为什么要冒险放弃经典的任务队列模式。它在大多数情况下都能正常工作。
【讨论】:
pthread_cond_wait,除非您持有保护共享状态的互斥锁。但我同意你们俩的观点,这种微观管理不太可能产生成效。
你可以这样做,但你是否真的想要是另一回事 - 请参阅其他帖子。
首先,忘记所有等待公共信号量的消费者线程。为了做你想做的事,等待的消费者线程必须通过实例来解决。为此,出现的消费者锁定队列并发现它为空,需要等待它自己的事件。此外,消费者需要在其“pop”调用中提供它想要放置对象的地址。因此,除了“普通”对象队列之外,需要等待的消费者线程还需要一个包含指针和要等待的事件的结构。您可以在创建 P-C 队列时创建这些 wait_struct 的数组或循环缓冲区。
那么你就准备好了。
PRODUCER:(使用对象 ref/ptr 调用 push) 获取队列锁并检查 wait_structs 列表。如果有一个条目,它将其对象加载到由 wait_struct 指针指向的地址中,(因此“直接向执行线程发送一个新的 producer()”),并发出 wait_struct 事件的信号。如果 wait_structs 列表中没有条目,则生产者将其对象放入对象队列中。哦,是的 - 释放队列锁:)
CONSUMER:(调用 pop 并使用它想要一个对象引用的地址) 获取队列锁并检查对象队列计数。如果它不为零,它会弹出对象,将其推入它提供的目标地址,释放锁并继续运行。如果对象队列为空,消费者在wait_structs列表中获得一个空闲的wait_strut,将指针设置为它传入的值,释放队列锁并等待事件。当事件发出信号时,消费者已经拥有了它的对象(由生产者推入),并且可以继续运行 - 无需再次访问 PC 队列。
是的,这种设计有效,(无论如何,在 Delphi 中 - 应该在 C++ 中工作),并且比“经典”基于信号量的 PC 队列更快(比 Windows 消息队列快,比IOCP 队列)。
我已经让它在超时的情况下工作 - 我会让你弄清楚如何做到这一点。 (提示 - 您必须使用消费者对象的位置,(由传入的指针寻址)作为临时存储:)
【讨论】: