join()函数的作用是让主线程的等待该子线程完成,然后主线程再继续执行。这种情况下,子线程可以安全的访问主线程中的资源。子线程结束后由主线程负责回收子线程资源。一个子线程只能调用join()和detach()中的一个,且只允许调用一次。可以调用joinable()来判断是否可以成功调用join()或detach()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <thread> #include <iostream>
using namespace std;
void test() { cout << "子线程开始执行!" << endl; //do something cout << "子线程执行完毕!" << endl; } int main() { cout << "主线程开始执行!" << endl; thread t(test); cout << "join()是否可调:" << boolalpha << t.joinable() << endl; t.join(); //主线程等待子线程 cout << "join()是否可调:" << boolalpha << t.joinable() << endl; cout << "主线程执行完毕!" << endl; return 0; }
结果输出:
主线程开始执行! join()是否可调:true 子线程开始执行! 子线程执行完毕! join()是否可调:false 主线程执行完毕!
|
注意
1、为了确保子线程程序在发送异常退出前完成,就需要对注意调用join()函数的位置,否则当主线发生异常而此时还没有调用到join()函数,那么子线程随主线程终止。解决方法是在异常处理中调用join()。
异常发生的情况,子线程没有完成就随主线程终止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <thread> #include <iostream>
using namespace std;
static void func() { cout << "子线程func开始执行!" << endl; //do something int i = 100000; while (i--) {} cout << "子线程func执行结束!" << endl; }
int main() { cout << "主线程main开始执行!" << endl; thread t(func); throw 123; t.join(); cout << "主线程main执行结束!" << endl; return 0; }
|

在异常处理中调用join()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <thread> #include <iostream> #include <cstdlib> //for rand()
using namespace std;
void func() { cout << "子线程func开始执行!" << endl; //do something int i = 100000; while(i--) { } cout << "子线程func执行结束!" << endl; }
int main() { cout << "主线程main开始执行!" << endl; thread t(func); try { //do something if (rand() % 7) //随机抛出异常来模拟异常发生 { throw 123; } } catch(...) { //do something t.join(); abort(); //终止主线程 } t.join(); //未发生异常时使用 cout << "主线程main执行结束!" << endl; return 0; }
|

2、为了应对忘记使用join()和选择位置的问题,可以使用RAII机制来管理子线程,在RAII析构中调用join()。这样在我根本不需要考虑join的位置问题,还是是否忘记的问题。但是这个方式在程序异常的情况下并不能保证主线程被终止时,子线程执行结束。因为程序因异常而终止时,如果没有捕获,对象的析构不会发生,只能由系统来回收资源。关于RAII:cpp中的RAII机制
使用RAII在析构中调用join()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <thread> #include <iostream>
using namespace std;
void func() { cout << "子线程func开始执行!" << endl; //do something int i = 100000 ; while(i--) { } cout << "子线程func执行结束!" << endl; }
class RAII_thread { thread& t; public: explicit RAII_thread(thread& t_): t(t_) { } ~RAII_thread(){ if(t.joinable()) t.join(); } RAII_thread(RAII_thread const&) = delete; RAII_thread& operator=(RAII_thread const&) = delete; };
int main() { //确保异常发生时,子线程执行完毕的技巧2,使用RAII管理子线程 cout << "主线程main开始执行!" << endl; thread t(func); RAII_thread raii(t); //do something cout << "主线程main执行结束!" << endl; return 0; }
|
