C ++ 11でスレッドを終了するにはどうすればよいですか?


137

スレッドを正しく終了したり、「終了」コマンドに応答させる必要はありません。純粋なC ++ 11を使用してスレッドを強制終了することに興味があります。


7
ここでは、このトピックに関する良い質問です:stackoverflow.com/questions/2790346/c0x-thread-interruption「すべての言語仕様がサポートが言語に組み込まれていないと言うが、」
ネマニャホウ

回答:


138
  1. std::terminate()どのスレッドからでも呼び出すことができ、参照しているスレッドは強制的に終了します。

  2. ~thread()ターゲットスレッドのオブジェクト上で、そのオブジェクトに介入するjoin()ことなくdetach()、そのオブジェクト上で実行されるように手配できます。これは、オプション1と同じ効果があります。

  3. 例外をスローするデストラクタを持つ例外を設計できます。そして、強制的に終了する場合に、ターゲットスレッドがこの例外をスローするように調整します。これに関するトリッキーな部分は、ターゲットスレッドがこの例外をスローするようにすることです。

オプション1と2はプロセス内リソースをリークしませんが、すべてのスレッドを終了します。

オプション3はおそらくリソースをリークしますが、ターゲットスレッドが例外をスローすることに同意する必要があるという点で、部分的に協調的です。

C ++ 11(私が承知している)には、マルチスレッドプログラムの単一のスレッドを協調せずに(つまり、すべてのスレッドを削除せずに)削除する移植可能な方法はありません。そのような機能を設計する動機はありませんでした。

A std::threadはこのメンバー関数を持っているかもしれません:

native_handle_type native_handle();

これを使用して、OS依存の関数を呼び出し、必要な処理を実行できる場合があります。たとえば、AppleのOSの場合、この関数は存在し、native_handle_typeですpthread_t。成功すると、リソースがリークする可能性があります。


2
「プロセス内リソースをリークしないでください」に関するわずかなヒント:もちろん、OSがプロセスを強制終了した後にすべてのリソースを再利用することは事実です、プログラムに関する限り、リソースリークされます。これは通常は無関係ですが、場合によっては問題となることもあります。std::terminate静的デストラクタを呼び出したり、出力バッファをフラッシュしたりしないため、リソースが解放される順序は明確に定義されていません。また、データがユーザーに表示されたり、永続ストアに書き込まれたり、さらには一貫して完全。
デイモン

6
exit()またはabort()全体的に同じ効果を呼び出すこともできます。
n。「代名詞」m。

2
#1は冗談で、@ ChrisDoddは正解です。冗談は#3の最初の文の回答で説明されています。Nanno Langstraatの回答とその下のコメントも参照してください。
ハワードHinnant

43

@ハワード・ヒンナントの答えは正確かつ包括的です。しかし、std::terminate()(プロセス全体で)たまたま@AlexanderVXが考えていた「終了」と同じ名前(1スレッド)を持っているので、あまりに速く読むと誤解される可能性があります。

要約:「1つのスレッドを強制終了+強制的に(ターゲットスレッドは連携しない)+純粋なC ++ 11 =不可能」


14
ああ、私の#1は本当に面白いです。強制的に終了するスレッドを指定する必要はありません。システムは、強制的に終了するものを魔法のように知っているだけで、それを実行します!
ハワードヒナント

8
はい、std::terminate()答えは古典的ないたずら好きなジンの話のようなものです。それは、OPの手紙への願いのすべてを満たしますが、おそらく彼の意図した方法ではありません。控えめなユーモアは私を笑わせました。:-)
Nanno Langstraat 2014年

2
無実のC ++初心者が望みをあまりにも長く/長くしすぎないようにする必要があります。
Nanno Langstraat、2014年

2
エレガントに述べた。:-)
ハワードヒンナン、2014年

@NannoLangstraat dammnit ...私が読むまで、私はそのような高い望みを持っていました:(..lol、まあ+1はすべて周り:)
code_fodder

13

この質問は実際にはより深い性質を持ち、一般的にマルチスレッドの概念をよく理解しているため、このトピックについての洞察が得られます。実際には、それらを使用しないよう警告せずに非同期でスレッドを強制終了する機能を提供する言語やオペレーティングシステムはありません。そして、これらのすべての実行環境は、開発者に強く助言するか、協調的または同期的なスレッド終了に基づいてマルチスレッドアプリケーションを構築することを要求します。この一般的な決定とアドバイスの理由は、それらすべてが同じ一般的なマルチスレッドモデルに基づいて構築されているためです。

マルチプロセッシングとマルチスレッディングの概念を比較して、2番目の概念の利点と制限をよりよく理解しましょう。

マルチプロセッシングは、オペレーティング環境全体がオペレーティングシステムによって制御される完全に分離されたプロセスのセットに分割されることを前提としています。プロセスは、プロセスのローカルメモリとプロセス内のデータ、およびファイル、ソケット、同期オブジェクトなどのすべてのシステムリソースを含む実行環境の状態を組み込み、分離します。分離は、プロセス境界による障害伝播を制限するため、プロセスの非常に重要な特性です。つまり、システム内の別のプロセスの一貫性に影響を与えるプロセスはありません。同じことがプロセスの動作にも当てはまりますが、制限が少なく、ぼやけた方法になります。このような環境では、最初に各プロセスが分離されるため、任意の「任意の」瞬間にプロセスを強制終了できます。次に、

対照的に、マルチスレッドは、同じプロセスで複数のスレッドを実行することを前提としています。ただし、このすべてのスレッドは同じ分離ボックスを共有しており、プロセスの内部状態をオペレーティングシステムで制御することはできません。その結果、どのスレッドもグローバルプロセスの状態を変更したり、破損したりできます。同時に、スレッドの状態がスレッドを強制終了しても安全であることがよく知られているポイントは、アプリケーションロジックに依存しており、オペレーティングシステムでもプログラミング言語ランタイムでも知られていません。その結果、任意の時点でスレッドが終了すると、実行パスの任意のポイントでスレッドが強制終了され、プロセス全体のデータの破損、メモリ、リークの処理に簡単につながる可能性があります。

このため、一般的なアプローチは、開発者に同期または協調スレッド終了を実装させることです。1つのスレッドが他のスレッド終了を要求し、明確なポイントの他のスレッドがこの要求をチェックして、明確な状態からシャットダウン手順を開始できます。すべてのグローバルシステム全体のリソースとローカルプロセス全体のリソースを安全かつ一貫した方法で解放します。


8
これはあまり役に立たない回答です。マルチプロセッシングはここでは関係ありません、そしてマルチスレッドについての観察はかなり広いです。
MSalters 2015年

4
私が言いたかったこと、そして詳細に述べたことは、マルチスレッドモデルは強力なスレッド終了の正式な方法を提供しないということです。C ++は、メモリモデル、マルチスレッドモデルなどの明確なモデルに従いたいと考えています。スレッドを強制終了する方法は本質的に安全ではありません。C ++標準委員会がそれをC ++に追加することを強制される場合、次のステートメントで行われます。「メソッドterminate()はスレッドの実行を終了します。動作は未定義です」。これは、「魔法をかけ、(おそらく)スレッドを終了するようなものです。 」
ZarathustrA 2015年

C#にはこの機能があります。
Derf Skren

@Derf Skren「実際には、それらを使用しないように警告せずに非同期でスレッドを強制終了する機能を提供する言語やオペレーティングシステムはありません。特に、現在のスレッド以外のスレッドを中止するためにそれを呼び出す場合、どのコードが実行されたか、実行に失敗したかわかりません... "(c)Microsoftリンク:docs.microsoft.com/en-us/dotnet/ api /…
ZarathustrA

11

OS依存の関数を使用してC ++スレッドを終了するヒント:

  1. std::thread::native_handle()join()またはを呼び出す前にのみ、スレッドの有効なネイティブハンドルタイプを取得できますdetach()。その後、native_handle()0を返します- pthread_cancel()コアダンプします。

  2. ネイティブスレッド終了関数(などpthread_cancel())を効果的に呼び出すには、std::thread::join()またはを呼び出す前にネイティブハンドルを保存する必要がありますstd::thread::detach()。そのため、ネイティブターミネーターは常に有効なネイティブハンドルを使用できます。

詳細については、http//bo-yang.github.io/2017/11/19/cpp-kill-detached-threadを参照してください。


5

強制終了する必要があるスレッドは、あらゆる種類の待機モードであるか、重い仕事をしていると思います。「素朴な」方法を使用することをお勧めします。

グローバルブール値を定義します。

std::atomic_bool stop_thread_1 = false;

スレッドが自然に終了するまで、コールスタック内のすべての関数が戻るように、次のコード(または同様のコード)をいくつかの重要なポイントに配置します。

if (stop_thread_1)
    return;

次に、別の(メイン)スレッドからスレッドを停止するには:

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.