二、线程的启动与结束 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 }
2.lambda表达式,泛型编程也是仿函数和lambda表达式成对出现
auto mylambda = [] (){ // [外部变量](返回值) cout << "lambda" << endl; } int main(){ thread myobj(mylambda); //myobj.join(); myobj.detach(); }
心之所愿,永不相忘