C++ 线程笔记之一:join和detach
ref
- blog:https://www.cnblogs.com/linuxAndMcu/p/14576565.html
- 《C++并发编程实战》第二版
前言
本文讲解关于C++11标准引入的std::thread类的join和detach方法。
join和detach
- 创建std::thread对象后,子线程会被创建,且该子线程会立即启动,没有显式的start函数启动子线程;
- std::thread对象 和 其创建的子线程 的生命周期不是绑定的,有可能std::thread对象在栈中已经被析构销毁但是子线程还在运行,有可能子线程已经结束退出但是std::thread对象还存在;
- 父线程创建子线程后必须要显式决定是join或者detach:
- 选择join,立刻阻塞父线程,等待子线程完成后,父线程再继续运行,并由父线程回收子线程的相关资源;
- 选择detach,分离子线程,子线程在后台运行(这种叫做守护线程),子线程的所有权和控制权转交给C++ runtime,子线程退出后由C++ runtime回收子线程的相关资源; 父线程的std::thread对象析构后,父线程不能够通过std::thread对象名与子线程通信;
- C++ 标准库的线程管理要求每个线程对象必须有一个明确的处理方式,要么被加入到主线程中,要么被分离; 否则线程对象生命周期结束时会触发未定义行为,通常表现为程序终止;《C++并发编程实战》第二版解释:“std::thread 的析构函数会调用 std::terminate(),即便是有异常存在,也需要确保线程能够正确汇入(joined)或分离(detached)。”
- 一旦子线程被detach,就不能够再被join,否则程序就会崩溃;可以使用joinable()函数判断一个线程对象能否调用join();
下文是代码验证,版本是g++ (GCC) 4.9.2。
join效果代码示例
#include <iostream>
#include <thread>
void threadTask() {
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "child thread" << std::endl;
}
void func() {
std::cout << "call func0" << std::endl;
std::thread t1(threadTask);
std::cout << "call func1, " << t1.joinable() << std::endl;
t1.join();
std::cout << "call func2, " << t1.joinable() << std::endl;
}
int main() {
func();
std::cout << "main thread" << std::endl;
return 0;
}
/*
编译和输出
g++ t1.cpp -o t1 --std=c++11 -lpthread
./t1
call func0
call func1, 1
child thread
call func2, 0
main thread
*/
detach代码示例
#include <iostream>
#include <thread>
void threadTask() {
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "hello thread" << std::endl; // 子线程运行到这里时,父线程已经退出,所以不会输出到终端里
}
void func() {
std::cout << "call func0" << std::endl;
std::thread t1(threadTask);
std::cout << "call func1, " << t1.joinable() << std::endl;
t1.detach(); // detach后,t1所在的函数栈结束导致t1析构,但是子线程还能继续存在
std::cout << "call func2, " << t1.joinable() << std::endl;
}
int main() {
func();
std::cout << "main thread" << std::endl;
return 0;
}
/*
编译和输出
g++ t2.cpp -o t2 --std=c++11 -lpthread
./t2
call func0
call func1, 1
call func2, 0
main thread
*/
既不join也不detach会发生什么?
#include <iostream>
#include <thread>
void threadTask() {
std::cout << "child thread" << std::endl;
}
void func() {
std::cout << "call func0" << std::endl;
std::thread t1(threadTask);
std::cout << "call func1, " << t1.joinable() << std::endl;
}
int main() {
func();
std::cout << "main thread" << std::endl;
return 0;
}
/*
编译和输出
g++ t3.cpp -o t3 --std=c++11 -lpthread
./t3
call func0
call func1, 1child thread
terminate called without an active exception
Aborted (core dumped)
./t3
call func0
call func1, 1
child thread
terminate called without an active exception
Aborted (core dumped)
*/
*/
浙公网安备 33010602011771号