web-dev-qa-db-ja.com

なぜスレッドを破棄する前にjoin()またはdetach()を呼び出さなければならないのですか?

なぜstd::threadは破壊され、join()またはdetach()状態である必要があります。

Joinはスレッドの終了を待ちますが、detachは終了しません。わからない中間状態があるようです。私の理解は、joinとdetachは相補的であるということです。join()を呼び出さない場合、detach()がデフォルトです。

つまり、スレッドを作成するプログラムを作成していて、このスレッドの存続期間の最後にjoin()を呼び出すとします。そのため、joinを呼び出すまで、スレッドは基本的に切り離されているかのように実行されていました。 ?

論理的にdetach()は、スレッドのデフォルトの動作である必要があります。これは、スレッドの定義であり、他のスレッドに関係なく並列に実行されるためです。

それで、スレッドオブジェクトが破壊されたとき、なぜterminate()が呼び出されるのですか?標準がスレッドを切り離されたものとして単に処理できないのはなぜですか?

スレッドが破棄される前にjoin()またはdetached()のいずれかが呼び出されなかった場合にプログラムを終了する理由を理解していません。これの目的は何ですか?

更新:

私は最近これに遭遇しました。 Anthony Williamsは彼の著書、Concurrency In Actionで次のように述べています。これは委員会でコンセンサスを得られなかったため、標準に受け入れられませんでした(ただし、C++ 20はstd :: jthreadとしてまだ順調です)...」

33
Moshe Rabaev

アクティブなスレッドのスレッドハンドルがスコープ外になると、いくつかのオプションがあります。

  1. 加わる
  2. 切り離す
  3. スレッドを殺す
  4. 殺害プログラム

これらのオプションのそれぞれがひどいです。どちらを選択しても、ほとんどの状況で意外と混乱し、望んでいたものとは異なります。


おそらく、あなたが言及した結合スレッドはすでに_std::async_の形で存在し、作成されたスレッドが完了するまでブロックする_std::future_を提供するため、暗黙的な結合を行います。しかし、理由に関する多くの質問

_std::async(std::launch::async, f);
g();
_

fgを同時に実行しないと、混乱を招きます。私が知っている最善のアプローチは、それをプログラミングエラーとして定義し、プログラマーに修正してもらうことです。そのため、assertが最も適切です。残念ながら、標準は代わりに_std::terminate_を使用しました。


デタッチスレッドが本当に必要な場合は、デストラクタまたは必要なハンドラでif (thread.joinable()) thread.detach();を実行する_std::thread_の周りに小さなラッパーを記述してください。

0
nwp