天天看点

二、线程的启动与结束 join与detach

主线程与子线程

默认情况下,主线程执行完后,那么所有子线程也会结束,整个程序执行完毕;除非用detach()分离子线程与主线程。

Thread:一个标准库中的类

join():阻塞主线程;加join() 的地方往往是主线程需要子线程的运行结果。

detach():分离子线程;当子程序很多时,让主线程一直等不太好,子线程在运行完后会自动被C++运行时库清理。

我们建议用join:阻塞主线程,让子线程先执行完,再继续执行主线程。

既然阻塞主线程了,那还有多线程的加速执行效果吗?

  有的,比如中间的循环(14~16行),这段代码是主线程和子线程并行执行的。

1 #include <thread>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 void myprint() //自己创建的线程也要从一个函数开始执行
 6 {
 7     cout << "start thread" << endl;
 8     cout << "end thread" << endl;
 9 }
10 
11 int main() {
12     //thread对象的构造函数接受的是一个可调用对象,创建了线程,线程执行起点myprint();
13     thread myobj(myprint);  
14     for (int i = 0; i < 100; i++) {
15         cout << "中间的代码" << endl;
16     }        
17     // 阻塞主线程,让主线程等待子线程执行完毕,然后主线程与子线程汇合继续执行,
18     // 当子线程执行完毕,join()就执行完毕,主线程继 续执行
19     myobj.join();  
20     cout << "good luck" << endl;
21     return 0;
22 }      

tip:一但调用了join()就不能再detach()了。

joinable():判读是否可以成功join()或者detach()的。返回true时可以join或者detach,返回false时不行。

1 #include <thread>
 2  
 3 vodi myprint() //自己创建的线程也要从一个函数开始执行
 4 {
 5     cout << "start thread" << endl;
 6     cout << "end thread" << endl;
 7 }
 8  
 9 int main(){
10     thread myobj(myprint); 
11  
12     if(myobj.joinable()){  //true
13         cout << "joinable() == ture" << endl;
14     }
15  
16     myobj.detach();  
17  
18     if(!myobj.joinable()){   //false
19         cout << "joinable() == false" << endl;
20     }
21  
22     cout << "good luck" << endl;
23     return 0;
24 }      

其他创建线程的方法:

  总的原则:可调用对象作为线程入口:函数指针、仿函数、lambda表达式、std::function

  1.用类的仿函数,可带参数

1 class CT
 2 {
 3 public:
 4     void operator()() //可调用对象
 5     {}
 6 };
 7  
 8 int main(){
 9     CT ct;
10     thread myobj(ct);
11     myobj.join();
12 }      
auto mylambda = [] (){  // [外部变量](返回值)
    cout << "lambda" << endl;
}
 
int main(){
    thread myobj(mylambda);
    //myobj.join();
    myobj.detach();
}      

心之所愿,永不相忘

继续阅读