正在终止自定义标准::线程池
Terminating custom std::thread pool
我最近一直在玩多线程游戏引擎架构和线程池。现在我实现了一个基本的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);
};
我想出了问题。这本身不是我的线程池实现的问题,但它与内核关闭时仍有任务到达的事实有关。因此,一些工作线程从未关闭,因此内核卡住了。向任务添加约束解决了这个问题。
相关文章:
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- 标准 cpp 数据结构和线程互斥锁?
- 标准::p set_value和线程安全
- C++ 线程时出错,标准::调用:
- C++ 杀死一个标准::线程
- 什么时候标准::线程::连接会因no_such_process而失败
- 将线程之间的标准输入/输出重定向
- 组合来自多个线程的数据的标准方法?
- 可以在构造函数初始值设定项列表中使用标准::线程
- 包装标准::线程调用函数
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- 是否使用符合标准的线程池进行 std::async 的 Visual C++ 实现
- 为什么Win API线程执行函数,而标准线程则没有
- 是否可以使用标准的C 线程而不是FLTK超时来更新窗口
- 标准C++11是否保证std::async(std::launch::asyncfunc)在单独的线程中启动func
- 代码::块无法识别标准::线程
- win32 标准::线程泄漏内存
- C++标准库容器相对于所包含对象的线程安全性
- 标准::线程::id的要求.可以雾化吗?
- C++ 标准::线程"Attempt to use a deleted function"