web-dev-qa-db-ja.com

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

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

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

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

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

オプション1と2はプロセス内リソースをリークしませんが、every threadを終了します。

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

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

std::threadには次のメンバー関数があります。

native_handle_type native_handle();

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

112
Howard Hinnant

@Howard Hinnantの答えは両方とも正しいおよび包括的です。しかし、std::terminate()(プロセス全体)が@AlexanderVXが念頭に置いていた「終了」と同じ名前(1スレッド)を持っているため、読みすぎた場合に誤解される可能性があります。

要約:「1スレッドの終了+強制的に(ターゲットスレッドは協力しません)+純粋なC++ 11 =ありません。」

34

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

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

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

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

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

8
ZarathustrA

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 を参照してください。

6
boyang

殺す必要のあるスレッドは、どのような種類の待機モードにあるか、重い仕事をしていると思います。 「単純な」方法を使用することをお勧めします。

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

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)
0
Doron Ben-Ari