做企业信用贷的网站,在自己电脑上做网站,网站开发使用api对seo,wordpress文章分集提示#xff1a;文章写完后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、thread详解二、线程何时运行三、线程启动方式1.join2.detach 总结 前言
无论哪种语言线程在绝大多数项目中都是会用到的#xff0c;C也一样#xff0c;C… 提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档 文章目录 前言一、thread详解二、线程何时运行三、线程启动方式1.join2.detach 总结 前言
无论哪种语言线程在绝大多数项目中都是会用到的C也一样C包装了一个std::thread类可以简化程序员的编程但在使用过程中也要注意区分用法否则可能适得其反。
今天要讨论的就是单纯的thread的join等待和detach分离两种情景让不懂得人看完之后茅塞顿开。 一、thread详解
C标准库成员是对线程的包装类在thread头文件里面使用方式是std::thread。创建线程本身就是通过创建一个thread类对象然后和系统线程完成绑定映射这样可以通过操作thread类对象来管理创建的系统线程系统线程本身行为受到内核调度机制影响。
示例代码
#include iostream
#include thread// 线程函数
void threadFunction() {std::cout Thread function is running std::endl;
}int main() {// 创建线程并启动std::thread t(threadFunction);// 等待线程完成t.join();std::cout Main thread is running std::endl;return 0;
}
注意这个地方如果不使用t.join()可能导致main线程早于子线程结束引发terminate
二、线程何时运行
这个问题一定要说清楚才行我以前用java的时候线程有一个start()可以决定什么时候启动线程C则不是这样C没有一个明确方法决定线程何时运行只需要满足创建并等待一般时间很短取决于实际情况直到线程获取了资源之后就会自动运行而不需要显式调用方法。且无论是以join还是detach方式启动的线程都受到内核的调度。
三、线程启动方式
1.join
主线程创建子线程的那个线程等待子线程执行完毕才进行下一步适合那种需要立刻得到结果的场景。创建方式很简单你只需要先创建线程然后在合适的时候调用t.join()等待结束即可。
示例代码
#include iostream
#include threadint main() {std::thread t([]{std::cout Lambda function is running std::endl;});t.join();std::cout Main thread is running std::endl;return 0;
}
当调用t.join()方法时主线程的等待直到t线程结束主线程才会继续运行程序结束。如果子线程里面有死锁主线程就会一直等待永无休止。
2.detach
在C中std::thread提供了一个detach方法可以将线程从其控制对象中分离。分离的线程会在后台独立运行直到完成。此方法常用于不需要同步或获取线程结果的情况。不过在使用detach时需要小心因为主线程不能再控制或管理该分离的线程这可能会导致资源管理和程序结束时的问题。
另外detach之后的变量不能重新join。
示例代码
#include iostream
#include thread
#include chronovoid worker() {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout Worker thread finished\n;
}int main() {std::thread t(worker);// 分离线程t.detach();std::cout Main thread finished\n;// 此处主线程可能已经结束而分离的线程仍在运行std::this_thread::sleep_for(std::chrono::seconds(3)); // 确保主线程不会立即退出return 0;
}
创建的子线程很快就会结束所以主线程3秒的休眠足够了如果子线程超过3秒就会导致主线程早于子线程结束程序terminate。
terminate called without an active exceptionProcess finished with exit code 3所以还是要面对一个问题detach后的线程怎么管理我并不能时时刻刻知道线程的状态如果主线程结束了子线程没结束怎么办方法还是有的那就是增加标志位同步需要atomic或锁如果我想一个线程结束只需要修改标志位。比如下面的代码
#include iostream
#include thread
#include atomic
#include chronostd::atomicbool keepRunning(true); // 原子布尔变量用于控制线程执行void threadFunction() {while (keepRunning) {std::cout Thread is running... std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout Thread stopped. std::endl;
}int main() {std::thread t(threadFunction);// 主线程等待一段时间后停止子线程std::this_thread::sleep_for(std::chrono::seconds(5));keepRunning false; // 设置标志位通知线程停止t.join(); // 等待线程结束std::cout Main thread is running std::endl;return 0;
}还可以借助boost库的方法来打断线程。例如
#include iostream
#include boost/thread.hppvoid threadFunction() {try {while (true) {// 执行一些工作boost::this_thread::interruption_point();}} catch (boost::thread_interrupted) {std::cout Thread interrupted. std::endl;}
}int main() {boost::thread t(threadFunction);// 主线程等待一段时间后中断子线程boost::this_thread::sleep_for(boost::chrono::seconds(5));t.interrupt(); // 中断线程t.join(); // 等待线程结束std::cout Main thread is running std::endl;return 0;
}
切记不要随意中断线程防止资源泄露不管是标志位、条件判断还是boost库都必须考虑资源回收的问题否则如果子线程里面使用了自由存储将永远无法得到回收。 总结
不管哪种方式启动的线程都要保证资源的回收特别是当心主线程早于子线程结束的情况。还有一种容易让人疏忽的情况如果你在一个函数里创建了thread对象你没有join或detach如果在函数return前线程没被回收就会导致terminate。比如下面的代码
void test(){
}void thread_join_detach(){std::thread t(test);
// t.detach();
// t.join();
}int main() {thread_join_detach();return 0;
}上面的代码thread_join_detach函数返回会回收t对象如果线程t还没结束就会terminate。解决方法有很多比较简单的就是在函数return之前调用join或detach还有就是把t提升作用域比如全局变量。