std::thread
std::thead是c++11用来创建线程的类,被定义在
std::thread myThread(函数名,函数参数...)
这个传入的参数和std::bind很像,将传入的函数参数绑定到传入的函数上,当然无参函数可以什么都不传。
看一个例子:
#include
#include
void testThread() {
//死循环
while (true) {
std::cout << "多线程测试函数" << std::endl;
}
}
int main() {
std::thread myThread(testThread);
for (int i = 0; i < 10; i++) {
std::cout << "\t\t主函数" << std::endl;
}
return 0;
}
这个例子是在主线程中打印10遍"主线程",然后在std::thread创建的线程中循环打印"多线程测试函数",观察结果我们发现主线程与子线程共同运行。
但是没过一会,系统崩溃了(vs环境下为崩溃,博主就是vs,devc环境下为卡死,过一会反回3)。
为什么会崩溃呢?仔细想一下,std::thread创建的是main函数的子线程,那么如果它不休止的运行下去,当main函数结束运行它还没结束的话,它该何去何从呢?只能崩溃了。接下来,让我们来解决这个问题。
std::thread::join()
std::thread的成员函数join()可以用来阻塞线程,它的作用是用来阻塞主线程直到子线程结束,然后再放行主线程。
std::thread myThread(testThread);
myThread.join();
值得注意的是,join()函数的位置就是阻塞的位置。
下面代码中,main函数里面的循环打印将永远不会执行,因为子线程是个死循环,并且它阻塞在了循环打印之前。
int main() {
std::thread myThread(testThread);
myThread.join();//阻塞
for (int i = 0; i < 10; i++) {
std::cout << "\t\t主函数" << std::endl;
}
return 0;
}
如果将join()函数放在main函数的循环打印之后,那么这个循环打印会被执行,但是执行完成以后不会return因为子线程还未结束,join()将会把主线程阻塞在那里。
int main() {
std::thread myThread(testThread);
for (int i = 0; i < 10; i++) {
std::cout << "\t\t主函数" << std::endl;
}
myThread.join();//阻塞
return 0;
}
加上join()函数之后,就不会像以前那样崩溃了,因为主线程将永远等待子线程结束,然后它再继续运行。
std::thread:detach()
detach()函数也是用来防止由于主线程提前结束而导致的子线程崩溃问题,它与join()不同的是,detach()并不阻塞线程,它直接将子线程与主线程分离,并将子线程提交给c++运行时库管理,在此之后我们将无法获得此子线程的权限。
int main() {
std::thread myThread(testThread);
myThread.detach();
for (int i = 0; i < 10; i++) {
std::cout << "\t\t主函数" << std::endl;
}
return 0;
}
在上节的例子中,由于join()会阻塞线程,所以导致主线程的循环打印无法执行,但是本例中使用了detach()主线程将不阻塞,但是主线程会提前结束,子线程依旧会继续运行,因为它被c++运行时库接管了。如下图所示,主线程结束后我们将看不见子线程的打印结果,但它依旧在执行。