Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当调用一个线程对象的析构函数,而该线程对象有一个条件变量在等待时,会发生什么?_C++_Multithreading_C++11_Condition Variable - Fatal编程技术网

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:引用的注释说明了采用这种方式的原因。