我有x个提升线程同时工作。一个生产者线程使用计算任务填充同步队列。消费者线程弹出任务并计算它们。
图片来源:https://www.quantnet.com/threads/c-multithreading-in-boost.10028/
用户可以在此过程中完成程序,因此我需要正确关闭我的线程。我当前的方法似乎不起作用,因为抛出异常。它的目的是在系统关闭时,所有进程都应该被杀死并且无论他们做什么都会停止当前的任务。你能告诉我,你怎么会杀死那些线程?
线程初始化:
for (int i = 0; i < numberOfThreads; i++)
{
std::thread* thread = new std::thread(&MyManager::worker, this);
mThreads.push_back(thread);
}
线程销毁:
void MyManager::shutdown()
{
for (int i = 0; i < numberOfThreads; i++)
{
mThreads.at(i)->join();
delete mThreads.at(i);
}
mThreads.clear();
}
工人:
void MyManager::worker()
{
while (true)
{
int current = waitingList.pop();
Object * p = objects.at(current);
p->calculateMesh(); //this task is internally locked by a mutex
try
{
boost::this_thread::interruption_point();
}
catch (const boost::thread_interrupted&)
{
// Thread interruption request received, break the loop
std::cout << "- Thread interrupted. Exiting thread." << std::endl;
break;
}
}
}
同步队列:
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
template <typename T>
class ThreadSafeQueue
{
public:
T pop()
{
std::unique_lock<std::mutex> mlock(mutex_);
while (queue_.empty())
{
cond_.wait(mlock);
}
auto item = queue_.front();
queue_.pop();
return item;
}
void push(const T& item)
{
std::unique_lock<std::mutex> mlock(mutex_);
queue_.push(item);
mlock.unlock();
cond_.notify_one();
}
int sizeIndicator()
{
std::unique_lock<std::mutex> mlock(mutex_);
return queue_.size();
}
private:
bool isEmpty() {
std::unique_lock<std::mutex> mlock(mutex_);
return queue_.empty();
}
std::queue<T> queue_;
std::mutex mutex_;
std::condition_variable cond_;
};
抛出的错误调用堆栈:
... std::_Mtx_lockX(_Mtx_internal_imp_t * * _Mtx) Line 68 C++
... std::_Mutex_base::lock() Line 42 C++
... std::unique_lock<std::mutex>::unique_lock<std::mutex>(std::mutex & _Mtx) Line 220 C++
... ThreadSafeQueue<int>::pop() Line 13 C++
... MyManager::worker() Zeile 178 C++
答案 0 :(得分:3)
根据我在Boost和Java中使用线程的经验,尝试从外部关闭线程总是很麻烦。我从来没有真正能够干净利落地工作。
我得到的最好的方法是为所有设置为true的消费者线程提供一个布尔值。当您将其设置为false时,线程将自行返回。在您的情况下,可以很容易地将其放入您的while循环中。
最重要的是,您需要进行一些同步,以便在删除之前等待线程返回,否则您可能会难以定义行为。
我过去的一个项目的例子:
线程创建
barrier = new boost::barrier(numOfThreads + 1);
threads = new detail::updater_thread*[numOfThreads];
for (unsigned int t = 0; t < numOfThreads; t++) {
//This object is just a wrapper class for the boost thread.
threads[t] = new detail::updater_thread(barrier, this);
}
线程破坏
for (unsigned int i = 0; i < numOfThreads; i++) {
threads[i]->requestStop();//Notify all threads to stop.
}
barrier->wait();//The update request will allow the threads to get the message to shutdown.
for (unsigned int i = 0; i < numOfThreads; i++) {
threads[i]->waitForStop();//Wait for all threads to stop.
delete threads[i];//Now we are safe to clean up.
}
线程包装器可能感兴趣的一些方法。
//Constructor
updater_thread::updater_thread(boost::barrier * barrier)
{
this->barrier = barrier;
running = true;
thread = boost::thread(&updater_thread::run, this);
}
void updater_thread::run() {
while (running) {
barrier->wait();
if (!running) break;
//Do stuff
barrier->wait();
}
}
void updater_thread::requestStop() {
running = false;
}
void updater_thread::waitForStop() {
thread.join();
}
答案 1 :(得分:0)
尝试移动&#39;尝试&#39; up(如下面的示例)。如果您的线程正在等待数据(在waitingList.pop()内),则可能在条件变量.wait()内等待。这是一个“中断点”。因此,当线程被中断时可能会抛出。
void MyManager::worker()
{
while (true)
{
try
{
int current = waitingList.pop();
Object * p = objects.at(current);
p->calculateMesh(); //this task is internally locked by a mutex
boost::this_thread::interruption_point();
}
catch (const boost::thread_interrupted&)
{
// Thread interruption request received, break the loop
std::cout << "- Thread interrupted. Exiting thread." << std::endl;
break;
}
}
}
答案 2 :(得分:0)
也许你正在捕捉错误的异常类? 这意味着它不会被抓住。 不太熟悉线程,但它是std :: threads和boost :: threads的混合导致了这个吗?
尝试捕获最低的父异常。
答案 3 :(得分:-2)
我认为这是读写器线程在公共缓冲区上工作的经典问题。解决此问题的最安全方法之一是使用互斥和信号。(我无法在此处发布代码。请发送电子邮件给我,我将代码发布给您)。