当调用具有条件变量等待的线程对象的析构函数时会发生什么? [英] What happens when calling the destructor of a thread object that has a condition variable waiting?

查看:455
本文介绍了当调用具有条件变量等待的线程对象的析构函数时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 SynchronisedQueue 在线程之间进行通信。我发现,当附加线程等待条件变量时,销毁线程对象会导致程序崩溃。这可以通过在线程销毁之前调用 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();
}
类型Dequeue(){
std :: unique_lock< std :: mutex> lock(mutex_);
while(queue_.empty())
condition_.wait(lock);
键入result = queue_.front();
queue_.pop();
return result;
}
private:
std :: queue< Type>队列_;
std :: mutex mutex_;
std :: condition_variable condition_;
};

class Worker {
public:
Worker(SynchronisedQueue< int> * queue):queue_(queue){}
void operator $ b queue _-> Dequeue(); //< - 线程在这里等待。
}
private:
SynchronisedQueue< int> * queue_;
};

int main(){
auto queue = new SynchronisedQueue< int>();
工人工人(队列);
std :: thread worker_thread(worker);
worker_thread。〜thread(); //< - 崩溃程序。
return 0;
}


解决方案

spec:

thread destructor [thread.thread.destr]〜thread(); p>

如果joinable(),调用std :: terminate()。



[注意:在其析构函数中隐式分离或加入joinable()线程可能会导致难以调试正确性(对于分离)或性能(用于联接)仅当引发异常时遇到的错误。因此,程序员必须确保在线程仍然可连接时,析构函数不会被执行。 - end note]


所以在没有先调用的情况下调用线程析构函数 c $ c> join (等待它完成)或 detach 是立即调用 std :: terminate 并结束程序。


I am using a SynchronisedQueue to communicate between threads. I found that destroying the thread object when the attaching thread is waiting on a condition variable would cause the program crash. This can be corrected by calling detach() before the thread destruction. But I am wondering what happens exactly when a thread waiting a conditional variable got terminated. Is there another way to use condition variable to avoid this?

#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;
}

解决方案

From the C++11 spec:

30.3.1.3 thread destructor [thread.thread.destr] ~thread();

If joinable(), calls std::terminate(). Otherwise, has no effects.

[ Note: Either implicitly detaching or joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is raised. Thus the pro grammer must ensure that the destructor is never executed while the thread is still joinable. — end note ]

So calling a thread destructor without first calling join (to wait for it to finish) or detach is guarenteed to immediately call std::terminate and end the program.

这篇关于当调用具有条件变量等待的线程对象的析构函数时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆