最近我一直在研究各种线程池架构 . “经典”线程池体系结构通常具有N个线程和单个共享任务队列 . 我认为只要个别任务足够大,这种架构就可以充分扩展 . 但是对于执行许多小任务的线程池,单个队列可能成为瓶颈 .

我通过我的研究发现的唯一一个解决这个问题的架构是"work-stealing" architecture . 而不是单个共享任务队列,每个线程有1个"private"任务队列 . 每个工作线程在其自己的专用队列上执行任务,然后当它没有更多任务时,它开始随机选择其他队列并且他们的任务 . 因此,只要存在更多任务,这就确保所有线程始终都有工作要做,并且它还解决了单队列瓶颈问题 .

但是,似乎永远不会提到的一个问题是这样的工作窃取队列如何能够保证所有CPU线程始终以与单个共享队列保证相同的方式使用 . 问题在于,在某些时候,当没有更多的工作要做时,线程池必须休眠 - 即它必须等待信号量或条件变量,直到更多的工作到达 . 否则,即使没有任何队列入队,线程池也会无休止地消耗CPU周期 . 但是如果一个工作窃取线程池必须要睡眠,可能需要一个与每个队列关联的信号量/条件变量 - 否则,如果它使用了共享信号量,我们又回到了单个共享队列的同一瓶颈问题 - 也就是说,每个 生产环境 者线程都需要与共享信号量/条件var的信令竞争 . 因此,这表明工作窃取线程池应该每个队列有一个sempahore / condition-variable .

但是,如果是这种情况,那么似乎没有任何保证线程池可以保证所有CPU将始终有效利用 . 例如,假设我们有8个线程和8个队列 . 所有线程都处于休眠状态,但线程[0]除外,它正忙于执行任务 . 现在, 生产环境 者线程运气不好,并在队列[0]上排队另一个任务 . 使用共享队列,新任务将立即由空闲线程执行 . 但是随着工作窃取池,其他7个线程只会闲置,因为他们从未被告知新任务,并且无法知道还有更多工作要做 .

这使我相信“工作窃取”线程池在高工作负载下可以很好地扩展,但是在低或“中”工作负载下,它永远不能保证所有线程实际上都被充分利用 .

那么在解决线程池工作的设计方面如何解决这个问题呢?