代码之家  ›  专栏  ›  技术社区  ›  Tyler

用于相互依存任务的线程池

  •  0
  • Tyler  · 技术社区  · 12 年前

    我有一个问题,在非递归的情况下,线程池很好地解决了这个问题,并且它将从任务(赋予池的工作/函数)中受益匪浅,能够向池中添加更多任务。我的线程池实现的问题是,第一级任务填充所有工作线程,创建第二级任务,然后在等待第二级完成任务时进行阻塞。由于所有工作线程都被阻塞,等待第二级完成,因此第二级任务永远不会执行,因此整个程序会死锁。

    对此有什么通用的解决方案吗?可能是一个抢占线程池(如果可能的话)。我确实考虑过明确区分任务的优先级,但问题是它不能自动处理依赖关系;它需要对API用户做更多的工作。

    提前感谢您的任何见解或建议。

    EDIT:线程池类定义

    class{
    public:
        thread_pool() = delete;
        thread_pool(const thread_pool&) = delete;
        thread_pool(unsigned int threads);
        ~thread_pool();
    
        template<class T, class... Args>
        std::future<T>
        async(std::function<T(Args...)>&& f, Args&&... args);
    
        template<class... Args>
        std::future<void>
        async(std::function<void(Args...)>&& f, Args&&... args);
    
        template<class T>
        std::future<T>
        async(std::function<T()>&& f);
    
        std::future<void>
        async(std::function<void()>&& f);
    
    protected:
        void init_threads();
        void join_threads();
    };
    
    1 回复  |  直到 12 年前
        1
  •  1
  •   Mihai Stan    12 年前

    您正在使用固定数量的线程,以防止出现过多的情况 忙碌的 同时执行任务,但当第一级任务等待第二级任务时,该线程不再 忙碌的 ,因此它不应再计入固定数量的运行线程。

    在我看来,你有两种方法来解决这个问题:

    1. 将螺纹标记为 忙碌的 当等待另一个任务时,告诉线程池它可以临时创建一个新线程来替换它。(这类似于Windows线程池 CallbackMayRunLong 功能)。

    2. 使用 任务完成回调 在第二级任务完成后恢复第一级任务,而不是等待它们。(类似于您使用 任务 在javascript中)。

    虽然更复杂,但第二个选项要灵活得多,std::bind为您提供了一些选项,用于在这些回调之间保留状态