调用具有条件变量的线程对象的析构函数时会发生什么?

时间:2012-12-21 03:45:33

标签: c++ multithreading c++11 condition-variable

我使用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();
  }
  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;
}

3 个答案:

答案 0 :(得分:14)

来自C ++ 11规范:

  

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

     

如果是joinable(),则调用std :: terminate()。否则,没有效果。

     

[注意:在析构函数中隐式分离或连接joinable()线程可能导致难以调试正确性(用于分离)或性能(用于连接)仅在引发异常时遇到错误。因此,程序员必须确保在线程仍可连接时永远不会执行析构函数。 - 结束说明]

所以在没有先调用thread destructor(等待它完成)或join的情况下调用detach,可以立即调用std::terminate并结束该程序。

答案 1 :(得分:2)

std::thread的析构函数如果没有调用std::terminate(等待线程完成)或join()(如果它在线程上运行)将调用detach()(将线程从对象上分离出来。

您的代码调用worker_thread的析构函数而不调用join()detach(),因此调用std::terminate。这与条件变量的存在无关。

答案 2 :(得分:-1)

在使用它的某些东西或者可能正在使用它时,你不能破坏资源。这真的只是常识。