如何在删除ThreadPool之前连接所有线程

时间:2018-02-23 14:30:34

标签: multithreading c++11 mutex

我正在使用MultiThreading类,它在自己的线程池中创建所需数量的线程,并在使用后删除自身。

std::thread *m_pool;      //number of threads according to available cores
std::mutex m_locker;
std::condition_variable m_condition;
std::atomic<bool> m_exit;
int m_processors    

m_pool = new std::thread[m_processors + 1]

void func()
{
   //code
}

for (int i = 0; i < m_processors; i++)
{
    m_pool[i] = std::thread(func);
}

void reset(void)
{
    {
        std::lock_guard<std::mutex> lock(m_locker);
        m_exit = true;
    }
    m_condition.notify_all();

    for(int i = 0; i <= m_processors; i++)
        m_pool[i].join();
    delete[] m_pool;
}

在执行完所有任务之后,for循环应该在执行delete[]之前加入所有正在运行的线程。
但似乎还有一个最后一个线程仍在运行,而m_pool不再存在 这导致了问题,我不能再关闭我的程序了 有没有办法检查所有线程是否已连接或等待所有线程在删除线程池之前加入?

2 个答案:

答案 0 :(得分:0)

我认为简单的拼写错误。

具有条件i <= m_processors的循环是错误,并且实际上会在数组末尾处理一个额外的条目。这是一个错误的错误。假设m_processors为2.您将拥有一个包含索引为[0]和[1]的2个元素的数组。然而,你将阅读数组的末尾,试图加入索引[2]的项目。 m_pool[2]是未定义的内存,你可能会在那里崩溃或永久阻塞。

您可能打算i < m_processors

答案 1 :(得分:0)

Wick的回答解决了问题的真正根源。我将通过一些技巧扩展它,这些技巧也可以解决您的问题,同时改进代码的其他方面。

如果对Vulkan使用C ++ 11,则不应使用std::thread创建线程句柄。有更好的方法可以使用其他C ++构造,这将使一切变得更简单和异常安全(如果抛出意外异常,则不会泄漏内存)。

  • 将您的线程对象存储在operator new[]中。它将为您管理内存分配和释放(不再是std::vectornew)。如果您动态插入/删除线程,则可以使用其他更灵活的容器,例如delete

  • 使用std::list或类似的

  • 填充矢量
std::generate
  • 使用range-for循环加入所有元素,并使用容器函数删除句柄。
std::vector<std::thread> m_pool;
m_pool.reserve(n_processors);

// Fill the vector
std::generate_n( std::back_inserter(m_pool), m_processors, 
                 [](){ return std::thread(func); } );