10

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

3 に答える 3

19

C ++ 11仕様から:

30.3.1.3スレッドデストラクタ[thread.thread.destr]〜thread();

joinable()の場合、std :: terminate()を呼び出します。それ以外の場合、効果はありません。

[注:デストラクタでjoinable()スレッドを暗黙的にデタッチまたは結合すると、例外が発生した場合にのみ発生する正確性(デタッチの場合)またはパフォーマンス(結合の場合)のバグのデバッグが困難になる可能性があります。したがって、プログラマーは、スレッドがまだ参加可能である間、デストラクタが実行されないようにする必要があります。—エンドノート]

したがって、thread destructor最初に呼び出さずに呼び出すjoin(終了するのを待つ)か、プログラム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 に答える