【C++同時およびマルチスレッド】2_スレッドの起動、終了、スレッドの作成に関するさまざまな方法、join,detach
7032 ワード
プレゼンテーションスレッドの実行の開始と終了は、main関数からメインスレッドが返されると、プロセス内の一意のメインスレッドが起動し、全体が終了するプロセスを実行することができる. で作成されたサブスレッドは、関数の実行が完了すると、現在のサブスレッドが終了する初期関数から実行する必要があります. プロセス終了フラグ:メインスレッドが終了したかどうか.プライマリ・スレッドの実行が完了すると、プロセス全体が終了します.通常、他のサブスレッドが完了していない場合、サブスレッドは強制的に終了します(例外:detach).
thread
スレッド実行オブジェクトを作成します.
join
サブスレッドの実行が終了するまで、メインスレッド(呼び出しスレッド)をブロックします.
detach
サブスレッドとプライマリスレッドの関連付けを分離すると、サブスレッドはシステムのバックグラウンドに存在して独立して実行を継続することができ、プライマリスレッドはプライマリスレッドの制御権を得ることができません.すなわち、プライマリスレッドが終了し、サブスレッドも終了しません.サブスレッドが終了すると、C++ランタイムライブラリがスレッド関連のリソースのクリーンアップを担当します.
joinable
スレッドオブジェクトがjoin()またはdetach()を呼び出すことができるかどうかを判断し、trueを返すことができ、falseを返すことができません.
Test1: thread, join, joinable
出力:
Test2: detach
出力:【プロセスが終了し、サブスレッドがバックグラウンドで実行され、コンソールで出力できません】
スレッドの作成方法
スレッドパラメータは呼び出し可能なオブジェクトです.呼び出し可能なオブジェクトには、関数、関数ポインタ、lambda式、std::bindで作成されたオブジェクト、std::functionで作成されたオブジェクト、および関数呼び出し演算子が再ロードされたクラスオブジェクトが含まれます.
出力:
説明:
注意:
呼び出し可能なクラスオブジェクトで作成されたスレッドオブジェクトにクラスオブジェクトのコピーがあります!!これにより、コピー動作がトリガーされ、パフォーマンスが損なわれる可能性があります.
thread
スレッド実行オブジェクトを作成します.
join
サブスレッドの実行が終了するまで、メインスレッド(呼び出しスレッド)をブロックします.
: joinable true ( false std::system_error )
detach
サブスレッドとプライマリスレッドの関連付けを分離すると、サブスレッドはシステムのバックグラウンドに存在して独立して実行を継続することができ、プライマリスレッドはプライマリスレッドの制御権を得ることができません.すなわち、プライマリスレッドが終了し、サブスレッドも終了しません.サブスレッドが終了すると、C++ランタイムライブラリがスレッド関連のリソースのクリーンアップを担当します.
: joinable true ( false std::system_error )
joinable
スレッドオブジェクトがjoin()またはdetach()を呼び出すことができるかどうかを判断し、trueを返すことができ、falseを返すことができません.
Test1: thread, join, joinable
#include
#include
using namespace std;
void thread_func()
{
cout << "thread_func begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "thread_func end" << endl;
}
int main()
{
cout << "main begin" << endl;
thread my_thread(thread_func);
if (my_thread.joinable()) // : join joinable !!!
{
cout << "my_thread.joinable() " << my_thread.joinable() << endl;
my_thread.join();
}
cout << "my_thread.joinable() " << my_thread.joinable() << endl;
cout << "main end" << endl;
return 0;
}
出力:
main begin
my_thread.joinable() 1
thread_func begin
thread_func end
my_thread.joinable() 0
main end
Test2: detach
#include
#include
using namespace std;
void thread_func()
{
cout << "thread_func begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "thread_func end" << endl;
}
int main()
{
cout << "main begin" << endl;
thread my_thread(thread_func);
if (my_thread.joinable())
{
my_thread.detach();
}
cout << "main end" << endl;
return 0;
}
出力:【プロセスが終了し、サブスレッドがバックグラウンドで実行され、コンソールで出力できません】
main begin
main end
スレッドの作成方法
スレッドパラメータは呼び出し可能なオブジェクトです.呼び出し可能なオブジェクトには、関数、関数ポインタ、lambda式、std::bindで作成されたオブジェクト、std::functionで作成されたオブジェクト、および関数呼び出し演算子が再ロードされたクラスオブジェクトが含まれます.
#include
#include
using namespace std;
void thread_func()
{
cout << "thread_func begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "thread_func end" << endl;
}
auto thread_lambda = []{
cout << "thread_lambda begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "thread_lambda end" << endl;
};
class thread_class {
public:
thread_class() {
cout << "thread_class " << this << endl;
}
thread_class(const thread_class&) {
cout << "thread_class(const thread_class&) " << this << endl;
}
~thread_class() {
cout << "~thread_class() " << this << endl;
}
void operator () () {
cout << "thread_class begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "thread_class end" << endl;
}
};
class base {
public:
void func()
{
cout << "base::func begin" << endl;
for (uint32_t i=0; i<10000; ++i)
{ }
cout << "base::func end" << endl;
}
};
int main()
{
cout << "main begin" << endl;
cout << "function:" << endl;
thread my_thread1(thread_func);
if (my_thread1.joinable())
my_thread1.join();
cout << "lambda:" << endl;
thread my_thread2(thread_lambda);
if (my_thread2.joinable())
my_thread2.join();
cout << "class:" << endl;
thread_class tc;
thread my_thread3(tc); // : !!
if (my_thread3.joinable())
my_thread3.join();
cout << "class::function:" << endl;
base b;
thread my_thread4(&base::func, &b);
if (my_thread4.joinable())
my_thread4.join();
cout << "main end" << endl;
return 0;
}
出力:
main begin
function:
thread_func begin
thread_func end
lambda:
thread_lambda begin
thread_lambda end
class:
thread_class 0x62fde7
thread_class(const thread_class&) 0x62fd77
thread_class(const thread_class&) 0x6917f8
~thread_class() 0x62fd77
thread_class begin
thread_class end
~thread_class() 0x6917f8
class::function:
base::func begin
base::func end
main end
~thread_class() 0x62fde7
説明:
?
QT5.15.2 STL
// 1. thread
template
explicit
thread(_Callable&& __f, _Args&&... __args)
{
#ifdef GTHR_ACTIVE_PROXY
// Create a reference to pthread_create, not just the gthr weak symbol.
auto __depend = reinterpret_cast(&pthread_create);
#else
auto __depend = nullptr;
#endif
_M_start_thread(_S_make_state(
__make_invoker(std::forward<_callable>(__f),
std::forward<_args>(__args)...)),
__depend);
}
// 2. __make_invoker __make_invoker
template
static _Invoker<__decayed_tuple _args...="">>
__make_invoker(_Callable&& __callable, _Args&&... __args)
{
return { __decayed_tuple<_callable _args...="">{
std::forward<_callable>(__callable), std::forward<_args>(__args)...
} };
}
// 3. __decayed_tuple tuple , tuple ,
template
using __decayed_tuple = tuple::type...>;
// 4. new _Impl{...},
template
static _State_ptr
_S_make_state(_Callable&& __f)
{
using _Impl = _State_impl<_callable>;
return _State_ptr{new _Impl{std::forward<_callable>(__f)}};
}
注意:
呼び出し可能なクラスオブジェクトで作成されたスレッドオブジェクトにクラスオブジェクトのコピーがあります!!これにより、コピー動作がトリガーされ、パフォーマンスが損なわれる可能性があります.