• 【C++多线程】join()及注意


    基础  

      join()函数的作用是让主线程的等待该子线程完成,然后主线程再继续执行。这种情况下,子线程可以安全的访问主线程中的资源。子线程结束后由主线程负责回收子线程资源。一个子线程只能调用join()和detach()中的一个,且只允许调用一次。可以调用joinable()来判断是否可以成功调用join()或detach()。

     1 #include <thread>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 void test()
     7 {
     8     cout << "子线程开始执行!" << endl;
     9     //do something
    10     cout << "子线程执行完毕!" << endl;
    11 }
    12 int main()
    13 {
    14     cout << "主线程开始执行!" << endl;
    15     thread t(test);
    16     cout << "join()是否可调:" << boolalpha << t.joinable() << endl;
    17     t.join();   //主线程等待子线程
    18     cout << "join()是否可调:" << boolalpha << t.joinable() << endl;
    19     cout << "主线程执行完毕!" << endl;
    20     return 0;
    21 }

     

    注意

      1、为了确保子线程程序在发送异常退出前完成,就需要对注意调用join()函数的位置,否则当主线发生异常而此时还没有调用到join()函数,那么子线程随主线程终止。解决方法是在异常处理中调用join()。

      异常发生的情况,子线程没有完成就随主线程终止。

     1 #include <thread>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 void func()
     7 {
     8     cout << "子线程func开始执行!" << endl;
     9     //do something
    10     int i = 100000;
    11     while(i--) { }
    12     cout << "子线程func执行结束!" << endl;
    13 }
    14 
    15 int main()
    16 {
    17     cout << "主线程main开始执行!" << endl;
    18     thread t(func);
    19     throw 123;
    20 21     t.join();
    22     cout << "主线程main执行结束!" << endl;
    23     return 0;
    24

     在异常处理中调用join()

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

     2、为了应对忘记使用join()和选择位置的问题,可以使用RAII机制来管理子线程,在RAII析构中调用join()。这样在我根本不需要考虑join的位置问题,还是是否忘记的问题。但是这个方式在程序异常的情况下并不能保证主线程被终止时,子线程执行结束。因为程序因异常而终止时,如果没有捕获,对象的析构不会发生,只能由系统来回收资源。关于RAII:https://www.cnblogs.com/chen-cs/p/13027205.html

      使用RAII在析构中调用join()

     1 #include <thread>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 void func()
     7 {
     8     cout << "子线程func开始执行!" << endl;
     9     //do something
    10     int i = 100000 ;
    11     while(i--) { }
    12     cout << "子线程func执行结束!" << endl;
    13 }
    14 
    15 class RAII_thread
    16 {
    17     thread& t;
    18 public:
    19     explicit RAII_thread(thread& t_): t(t_) { }
    20     ~RAII_thread(){
    21         if(t.joinable()) 
    22             t.join();
    23     }
    24     RAII_thread(RAII_thread const&) = delete; 
    25     RAII_thread& operator=(RAII_thread const&) = delete;
    26 };
    27 
    28 
    29 
    30 int main()
    31 {
    32 
    33     //确保异常发生时,子线程执行完毕的技巧2,使用RAII管理子线程
    34     cout << "主线程main开始执行!" << endl;
    35     thread t(func);
    36     RAII_thread raii(t);
    37     //do something
    38     cout << "主线程main执行结束!" << endl;
    39     return 0;
    40 }

  • 相关阅读:
    iOS开发UI篇—使用storyboard创建导航控制器以及控制器的生命周期
    IOS开发UI篇—导航控制器属性和基本使用
    基于XMPP协议的aSmack源码分析
    XMPP-for-Android
    wecontact
    MyPhone
    Video conference server OpenMCU-ru
    WebRTC_Wrapper
    Sip-MCU
    WebRTC学习笔记
  • 原文地址:https://www.cnblogs.com/chen-cs/p/13055211.html
Copyright © 2020-2023  润新知