没有detach线程线程退出后通过join回收线程的资源如果没有join那么会出现内存泄漏detach的线程在线程退出后资源会自动回收。资源包括线程的栈资源线程描述符等。1join等待线程退出用于线程间同步特别是在主线程退出的时候等待进程中的所有其它线程都退出之后主线程再退出这样能保证进程安全的退出。试想如果主线程退出的时候有其它线程还在运行很容易导致进程的退出码不是0或者被信号杀死。因为进程退出的时候就要释放所有的资源而此时还在运行的线程可能会使用已经释放的资源这样就会导致段错误。调用join之前需要使用joinable进行判线程是不是可join如果线程不可join那么调用join会抛异常。#include iostream #include thread #include unistd.h int main() { std::thread t([]() { for (int i 0; i 10; i) { std::cout i i std::endl; sleep(1); } }); if (t.joinable()) { std::cout join thread std::endl; t.join(); } return 0; }2detach线程执行与线程对象隔离不可join如下代码detach之后线程与std::thread对象已经分离了这个时候std::thread对象无法控制线程。即使std::thread对象析构线程也会照样继续执行。detach之后再调用join会抛异常。#include iostream #include thread #include unistd.h int main() { std::thread t([]() { for (int i 0; i 10; i) { std::cout i i std::endl; sleep(1); } }); t.detach(); if (t.joinable()) { std::cout join thread std::endl; t.join(); } else { std::cout thread is not joinable std::endl; try { t.join(); } catch (std::exception e) { std::cout exception: e.what() std::endl; } } return 0; }3如果线程已经退出这时调用join是什么现象?joinable返回1线程仍然是可以join的调用join会立即返回。调用join之后线程就不是可join的了joinable返回0。join在线程和线程之间就类似于wait在父子进程之间的关系:子进程退出之后父进程wait相当于给子进程收尸线程退出之后那么调用join的线程也相当于给这个线程收尸所以说join之后线程就不是可join的了。#include iostream #include thread #include unistd.h int main() { std::thread t([]() { for (int i 0; i 2; i) { std::cout i i std::endl; sleep(1); } }); sleep(5); std::cout joinable t.joinable() std::endl; try { t.join(); std::cout joinable t.joinable() std::endl; } catch (std::exception e) { std::cout 异常 e.what() std::endl; } return 0; }4std::thread默认构造函数默认构造函数不会启动一个线程也不能join不能detach调用join和detach均会抛出异常。#include iostream #include thread #include unistd.h int main() { std::thread t; std::cout joinable t.joinable() std::endl; t std::thread([]() { for (int i 0; i 10; i) { std::cout i i std::endl; sleep(1); } }); if (t.joinable()) { std::cout join thread std::endl; t.join(); } return 0; }一个不能join的线程那么也是不能detach的。下边的代码如果没有调用t1.join那么调用t1.detach不会抛异常调用join之后再调用detach会抛异常。#include thread #include iostream #include unistd.h void create() { std::cout create std::endl; } int main() { std::thread t1(create); sleep(2); t1.join(); t1.detach(); return 0; }那么默认构造有什么用途呢先声明后启动让启动时可控的或者说是后初始化作为类成员class WorkerPool { private: std::thread worker_; // 默认构造 public: void start() { worker_ std::thread(WorkerPool::run, this); } void stop() { if (worker_.joinable()) { worker_.join(); } } };作为容器std::vectorstd::thread threads; threads.reserve(10); // 先分配空间避免动态扩容 // 稍后创建并填充线程 for (int i 0; i 10; i) { threads.emplace_back(worker_func, i); }延迟初始化std::thread worker; // 默认构造不关联线程 // 稍后根据条件创建线程 if (some_condition) { worker std::thread(task_function, arg1, arg2); }5native_handleget_id和native_handler返回的均是pthread id即posix thread id与pthread_self获取的id是一致的。使用pthread相关的api的时候(pthread_getschedparam、pthread_join、pthread_detach等)均需要传这个参数。#include iostream #include thread #include unistd.h int main() { std::thread t; std::cout joinable t.joinable() std::endl; std::cout id: t.get_id() std::endl; t std::thread([]() { std::cout pthread id: pthread_self() std::endl; for (int i 0; i 10; i) { std::cout i i std::endl; sleep(1); } }); std::cout id: t.get_id() std::endl; std::cout native: t.native_handle() std::endl; if (t.joinable()) { std::cout join thread std::endl; t.join(); } return 0; }