What happens when calling the destructor of a thread object that has a condition variable waiting?

有些话、适合烂在心里 提交于 2019-11-26 20:59:24

问题


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

回答1:


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.




回答2:


The destructor for std::thread will call std::terminate if it is run on a thread if you not have called join() (to wait the thread to finish) or detach() (to detach the thread from the object) on it.

Your code calls the destructor for worker_thread without calling join() or detach() on it, and so std::terminate is called. This is unrelated to the presence of condition variables.




回答3:


You cannot, ever, destroy a resource while something is, or might be, using it. That's really just common sense.



来源:https://stackoverflow.com/questions/13983984/what-happens-when-calling-the-destructor-of-a-thread-object-that-has-a-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!