C++ 当调用一个线程对象的析构函数,而该线程对象有一个条件变量在等待时,会发生什么?
我正在使用C++ 当调用一个线程对象的析构函数,而该线程对象有一个条件变量在等待时,会发生什么?,c++,multithreading,c++11,condition-variable,C++,Multithreading,C++11,Condition Variable,我正在使用同步队列在线程之间进行通信。我发现在附加线程等待条件变量时销毁线程对象会导致程序崩溃。这可以通过在线程销毁之前调用detach()来纠正。但是我想知道当一个等待条件变量的线程被终止时会发生什么。有没有其他方法可以使用条件变量来避免这种情况 #include <queue> #include <thread> #include <mutex> #include <condition_variable> template <typen
同步队列
在线程之间进行通信。我发现在附加线程等待条件变量时销毁线程对象会导致程序崩溃。这可以通过在线程销毁之前调用detach()
来纠正。但是我想知道当一个等待条件变量的线程被终止时会发生什么。有没有其他方法可以使用条件变量来避免这种情况
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
template <typename Type> class SynchronisedQueue {
public:
void Enqueue(Type const & data) {
std::unique_lock<std::mutex> lock(mutex_);
queue_.push(data);
condition_.notify_one();
}
Type Dequeue() {
std::unique_lock<std::mutex> lock(mutex_);
while (queue_.empty())
condition_.wait(lock);
Type result = queue_.front();
queue_.pop();
return result;
}
private:
std::queue<Type> queue_;
std::mutex mutex_;
std::condition_variable condition_;
};
class Worker {
public:
Worker(SynchronisedQueue<int> * queue) : queue_(queue) {}
void operator()() {
queue_->Dequeue(); // <-- The thread waits here.
}
private:
SynchronisedQueue<int> * queue_;
};
int main() {
auto queue = new SynchronisedQueue<int>();
Worker worker(queue);
std::thread worker_thread(worker);
worker_thread.~thread(); // <-- Crashes the program.
return 0;
}
#包括
#包括
#包括
#包括
模板类同步队列{
公众:
无效排队(常量和数据类型){
std::唯一锁(互斥锁);
队列推送(数据);
条件u.通知u one();
}
类型Dequeue(){
std::唯一锁(互斥锁);
while(queue_u.empty())
条件等待(锁定);
类型result=queue_.front();
queue_u2;.pop();
返回结果;
}
私人:
std::队列;
std::mutex mutex;
std::条件u可变条件u;
};
班主任{
公众:
工作者(同步队列*队列):队列{(队列){}
void运算符()(){
queue->Dequeue();//当某个资源正在或可能正在使用时,您永远无法销毁该资源。这只是常识。如果未调用join()
(等待线程完成)或detach(),则std::thread
的析构函数将调用std::terminate
(从对象上拆下螺纹)在其上
您的代码调用worker\u thread
的析构函数,而不在其上调用join()
或detach()
,因此调用std::terminate
。这与条件变量的存在无关。来自C++11规范:
30.3.1.3线程析构函数[thread.thread.destr]~thread()
如果joinable(),则调用std::terminate()。否则,将不起作用
[注意:隐式分离或在其析构函数中加入joinable()线程可能会导致难以调试正确性(用于分离)或性能(用于连接)错误,只有在引发异常时才会遇到。因此,编程人员必须确保在线程仍然可连接的情况下,析构函数永远不会执行。-结束注意]
因此,调用线程析构函数
,而不首先调用join
(等待它完成)或者detach
被保证立即调用std::terminate
并结束程序。我测试了它。你是对的。如果工作线程是可连接且正在运行的,你甚至不能让主线程返回。所以我猜这个答案()是错误的,因为std::terminate()或~thread()当线程是可连接的并且正在运行时,会导致程序而不是线程终止。@WiSaGaN:如果你阅读它,答案实际上就是这么说的。好的。我看到“但是它们终止了每个线程”。而joinable()
是检查你是否可以安全地调用~thread()的唯一标准
。即使线程已经完成了线程体,也必须先调用joinable()
或detach()
,才能安全地销毁线程对象。您能否详细说明一下为什么标准是这样做的。为什么不在d中调用join()-tor@Nick:引用的注释说明了采用这种方式的原因。