web-dev-qa-db-ja.com

C ++のマルチスレッドのjoin()とdetach()の違いは何ですか?

C++のマルチスレッドでのjoin()detach()の違いは何ですか? join()はスレッドを強制終了しますか?

17
r.hg

C++ threadオブジェクトは一般に(常にではありませんが)OSまたはプラットフォームの概念である実行のスレッドを表します。

thread::join()が呼び出されると、呼び出しスレッドは実行スレッドが完了するまでブロックします。基本的に、これはスレッドがいつ終了したかを知るために使用できるメカニズムの1つです。 thread::join()が戻ると、OSの実行スレッドが完了し、C++ threadオブジェクトを破棄できます。

thread::detach()が呼び出され、実行スレッドがthreadオブジェクトから「切り離され」、threadオブジェクトによって表されなくなります。これらは2つの独立したものです。 C++ threadオブジェクトを破棄し、OSの実行スレッドを続行できます。プログラムがその実行スレッドがいつ完了したかを知る必要がある場合、他のメカニズムを使用する必要があります。 join()は、そのthreadオブジェクトで実行できなくなりました。実行のスレッドに関連付けられなくなったためです。

C++ threadオブジェクトを「結合可能」のまま破棄するとエラーと見なされます。つまり、C++ threadオブジェクトを破棄するには、join()を呼び出す(および完了する)か、detach()を呼び出す必要があります。 C++ threadオブジェクトが破棄されたときにまだ結合可能な場合、例外がスローされます。

C++ threadオブジェクトが実行のスレッドを表さない他のいくつかの方法(つまり、結合できないことがあります):

  • デフォルトで構築されたthreadオブジェクトは実行のスレッドを表さないため、結合できません。
  • 移動されたスレッドは実行のスレッドを表さないため、結合できません。
30
Michael Burr

join()はスレッドを強制終了しません。実際には、スレッドのメイン関数が戻るまで待機します。したがって、スレッドのメイン関数が次のようになっている場合:

_while (true) {
}
_

join()は永遠に待機します。

detatch()もスレッドを殺しません。実際、_std::thread_オブジェクトが破棄された場合でも、このスレッドは実行を継続する必要があることを_std::thread_に伝えます。 C++はstd :: threadデストラクターでスレッドが結合または切り離されていることをチェックし、このチェックが失敗するとプログラムを終了します。

したがって、次のコードのmain関数の最初の行のコメントを解除すると、クラッシュします。 2行目または3行目のコメントを外すと正常に機能します。

_#include <thread>

void func() {
}

void fail1() {
    std::thread t(func);
    // will fail when we try to destroy t since it is not joined or detached
}

void works1() {
    std::thread t(func);
    t.join();
}

void works2() {
    std::thread t(func);
    t.detach();
}

int main() {
    // fail1();
    // works1();
    // works2();
}
_
11
dim-an