10

我正在使用 aSynchronisedQueue在线程之间进行通信。我发现当附加线程正在等待条件变量时销毁线程对象会导致程序崩溃。这可以通过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;
}
4

3 回答 3

19

来自 C++11 规范:

30.3.1.3线程析构函数 [thread.thread.destr] ~thread();

如果 joinable(),则调用 std::terminate()。否则,没有任何影响。

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

因此,在thread destructor没有先调用join(等待它完成)的情况下调用 a 或者detach保证立即调用std::terminate并结束程序。

于 2012-12-21T04:12:50.573 回答
2

如果您没有调用(等待线程完成)或(将线程与对象分离),则析构函数std::thread将在线程上运行时调用。std::terminatejoin()detach()

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

于 2012-12-21T04:09:50.570 回答
-1

当某物正在或可能正在使用它时,您永远不能破坏资源。这真的只是常识。

于 2012-12-21T03:59:10.233 回答