正在终止自定义标准::线程池



我最近一直在玩多线程游戏引擎架构和线程池。现在我实现了一个基本的Kernel类。此类有一个 std::vector<std::thread> ,它表示线程池。现在,以下函数由池中的单个线程运行:

while(m_IsRunning)
{
    std::unique_lock<std::mutex> kernelstateLocker(m_KernelStateMutex);
    m_KernelStateCond.wait(kernelstateLocker);
    if(m_KernelState == KernelState::KernelShutdown || m_KernelState == KernelState::KernelTerminate)
    {
        kernelstateLocker.unlock();
        //std::cout << "Worker #" << _workerID << std::endl console log here
        break;
    }
    else if(m_KernelState == KernelState::KernelWorkAvailable)
    {
        ...
}

如您所见,如果KernelState变量发生变化,线程就会唤醒。当将任务添加到队列或内核关闭时,可能会发生这种情况。内核关闭条件变量由主程序线程通过 m_KernelStateCond.notify_all() 调用。但是,正如我在注释中看到cout添加的那样,有时最多 8 个工作线程中只有一个会打印其名称和 id,表明其他线程从未终止。有谁知道为什么会这样,以及如何终止池中的所有线程?如果很重要,我的平台是Windows 64 64位上的TDM-GCC-5.1 64位。

更新:

根据注释请求和 SO 规则,以下是调用条件变量的代码。

std::unique_lock<std::mutex> shutdownLocker(m_IsRunningMutex);
m_ShutdownCond.wait(shutdownLocker, [this](){ return !m_IsRunning; });
if(!m_IsRunning)
{
    shutdownLocker.unlock();
    m_KernelStateMutex.lock();
    m_KernelState = KernelState::KernelShutdown;
    m_KernelStateMutex.unlock();
    m_KernelStateCond.notify_all();
}

我很确定我的这部分代码正在工作,因为至少有一个线程工作线程实际上关闭了。为了完整起见,这是我的完整Kernel课程:

class Kernel : public Singleton<Kernel>
{
public:
    void boot(unsigned int _workerCount);
    void run();
    void shutdown();
    void addTask(std::shared_ptr<Task> _task);
private:
    friend class Singleton<Kernel>;
    Kernel();
    ~Kernel();
    bool m_IsRunning;
    KernelState m_KernelState;
    std::vector<std::thread> m_Workers;
    std::queue<std::shared_ptr<Task>> m_Tasks;
    std::vector<std::shared_ptr<Task>> m_LoopTasks;
    std::condition_variable m_KernelStateCond;
    std::mutex m_KernelStateMutex;
    void workTask(unsigned int _workerID);
};

我想出了问题。这本身不是我的线程池实现的问题,但它与内核关闭时仍有任务到达的事实有关。因此,一些工作线程从未关闭,因此内核卡住了。向任务添加约束解决了这个问题。

最新更新