177

std::threadを開始し、次にそれを開始すると仮定するとdetach()、スレッドはstd::thread、かつてそれを表していた が範囲外になっても実行を続けます。

さらに、切り離されたスレッド1に参加するための信頼できるプロトコルがプログラムにないため、終了時に切り離されたスレッドが引き続き実行されると仮定しmain()ます。

標準 (より正確には、N3797 C++14 ドラフト) には、何が起こるべきかを説明するものは何も見つかりません。

1別の、おそらく同等の質問は、「切り離されたスレッドを再び参加できるか」です。これは、参加するために発明しているプロトコルが何であれ、スレッドがまだ実行されている間にシグナリング部分を実行する必要があり、OS スケジューラがスレッドが実際に終了したことを受信側が確実に検出する方法がないため、シグナリングが実行された直後にスレッドを 1 時間スリープさせることにしました。

main()分離されたスレッドが実行されている状態で不足することが未定義の動作である場合、メインスレッドが決して終了しない限り、 の使用は未定義動作です2std::thread::detach()

したがって、切り離されたスレッドが実行されている状態で不足すると、定義された効果が発生main()するはずです。問題は ( C++ 標準では、POSIX ではなく、OS ドキュメントではなく、...) これらの効果が定義されている場所です。

2切り離されたスレッドを結合することはできません ( の意味でstd::thread::join())。切り離されたスレッドからの結果を待つことはできますが (たとえば、future from を介してstd::packaged_task、またはカウント セマフォまたはフラグと条件変数によって)、スレッドが の実行を終了したことを保証するものではありません。実際、シグナル部分をスレッドの最初の自動オブジェクトのデストラクタに入れない限り、一般に、シグナル コードのに​​実行されるコード (デストラクタ) が存在します。切り離されたスレッドが上記のデストラクタの実行を終了する前に、OS がメイン スレッドが結果を消費して終了するようにスケジュールした場合、何が起こると定義されていますか?

4

7 に答える 7

44

スレッドの切り離し

によるとstd::thread::detach

スレッド オブジェクトから実行スレッドを分離し、独立して実行を継続できるようにします。割り当てられたリソースは、スレッドが終了すると解放されます。

からpthread_detach:

pthread_detach() 関数は、スレッドの終了時にスレッドのストレージを再利用できることを実装に示す必要があります。スレッドが終了していない場合、pthread_detach() はスレッドを終了させません。同じターゲットスレッドに対する複数の pthread_detach() 呼び出しの影響は規定されていません。

スレッドの切り離しは主に、アプリケーションがスレッドの終了を待つ必要がない場合 (プロセスが終了するまで実行する必要があるデーモンなど) に備えて、リソースを節約するためのものです。

  1. アプリケーション側のハンドルを解放するには:std::threadオブジェクトを結合せずにスコープ外に出すことができます。これは、通常、std::terminate()破棄の呼び出しにつながります。
  2. スレッドが終了するとすぐに OS がスレッド固有のリソース ( TCB ) を自動的にクリーンアップできるようにするには、後でスレッドに参加することに関心がないことを明示的に指定したため、既に切り離されたスレッドに参加することはできません。

スレッドを殺す

プロセス終了時の動作は、少なくともいくつかのシグナルをキャッチできるメイン スレッドの動作と同じです。他のスレッドがシグナルを処理できるかどうかはそれほど重要ではありません。メイン スレッドのシグナル ハンドラー呼び出し内で他のスレッドに参加したり終了したりできるからです。(関連質問)

すでに述べたように、分離されているかどうかに関係なく、ほとんどの OS でスレッドはそのプロセスで終了します。プロセス自体は、シグナルを発生させるか、呼び出すexit()か、メイン関数から戻ることによって終了できます。ただし、C++11 は基盤となる OS の正確な動作を定義することはできませんし、試みもしませんが、Java VM の開発者はそのような違いをある程度抽象化できます。私の知る限り、エキゾチックなプロセスとスレッドモデルは通常、古代のプラットフォーム (おそらく C++11 は移植されないでしょう) やさまざまな組み込みシステムで見られます。これらのシステムには、特別な言語ライブラリの実装や限定的な言語ライブラリの実装、および限定的な言語サポートが含まれる可能性があります。

スレッドサポート

スレッドがサポートされていない場合、実行するスレッド オブジェクトを必要とせず、 a のコンストラクターがをスローする必要があるプレーン プロセスがあるため、スレッドはstd::thread::get_id()無効な ID (デフォルトで構築された ) を返す必要があります。これが、今日の OS と組み合わせて C++11 を理解する方法です。プロセスでメイン スレッドを生成しない、スレッド化をサポートする OS がある場合は、お知らせください。std::thread::idstd::threadstd::system_error

スレッドの制御

適切なシャットダウンのためにスレッドを制御し続ける必要がある場合は、同期プリミティブや何らかのフラグを使用してそれを行うことができます。ただし、この場合、シャットダウンフラグを設定してから結合するのが私が好む方法です。スレッドを切り離して複雑さを増しても意味がないためです。リソースはとにかく同時に解放されるため、std::threadオブジェクトの数バイトがより複雑で、場合によってはより多くの同期プリミティブが受け入れられるはずです。

于 2013-11-02T17:17:54.643 に答える
20

プログラムが終了した後のスレッドの運命は、未定義の動作です。しかし、最新のオペレーティング システムでは、プロセスを閉じるときにプロセスによって作成されたすべてのスレッドがクリーンアップされます。

をデタッチするstd::threadと、次の 3 つの条件が引き続き保持されます。

  1. *thisはもはやどのスレッドも所有していません
  2. joinable()常に等しいfalse
  3. get_id()等しくなりますstd::thread::id()
于 2013-11-02T16:47:50.030 に答える
7

メイン スレッド (つまり、main() 関数を実行するスレッド) が終了すると、プロセスが終了し、他のすべてのスレッドが停止します。

参考:https ://stackoverflow.com/a/4667273/2194843

于 2017-05-03T10:15:22.740 に答える