管理线程之等待线程结束
来源:互联网 发布:初中作文大全软件 编辑:程序博客网 时间:2024/04/28 08:11
正常环境下等待线程结束
如果需要等待线程结束,就在线程的实例对象上调用join()。在管理线程之创建线程最后的例子中,用my_thread.join()代替my_thread.detach()就可以确保在函数终止前、局部变量析构前,线程会终止。在这种情况下,用分开的线程来运行函数就没有什么意义了。因为在等待my_thread终止时,这个线程就不做任何事情了。在实际的工程应用中,要么这个线程做自己的事,要么创建多个线程等待它们结束。
join()是简单粗暴的,或者你等待线程终止,或者你不等待。如果想要更加精确控制,例如检查这个线程是否终止,或只是等待某一段时间,这是你必须使用其他方法例如条件变量等。线程调用join()会清理相应的内存空间,调用join()后,std::thread对象就不再和这个线程相关了。这也就是意味着,对于一个线程实例对象,你仅仅可以调用join()一次,在调用后,这个线程对象就不在是joinable,调用joinable()会返回false。
异常环境下的情况
在线程对象销毁前,必须确保调用了join()或detach()。如果要分离一个线程,通常是在创建线程后立即调用detach(),因此这不是问题。但是如果要等待一个线程,那么必须小心去找到在代码的什么地方调用join()。也就是说,因为异常的发生,join()有可能被跳过而得不到执行。
为了避免应用程序在异常时终止,要考虑到在异常情况下怎么做。通常来讲,在没有异常情况下如果调用join(),那么再异常情况下也需要调用join(),这样才可以避免意外的生命周期的问题。在实际代码中,可以使用try/catch:
struct func;void f(){int some_local_state=0;func my_func(some_local_state);std::thread t(my_func);try{do_something_in_current_thread();}catch(...){t.join();throw;}t.join();}上面代码使用try/catch模块来确保调用join(),无论是否发生异常。使用try/catch有点冗长(verbose),而且容易出现作用域错误,不是理想的解决方法。
另一种方法是RAII(Resource Acquisition Is Initialization资源获取即初始化),在类的析构函数中调用join()
class thread_guard{std::thread& t;public:explicit thread_guard(std::thread& t_):t(t_){}~thread_guard(){if(t.joinable())//先检查是否已经掉用过joint.join();}//下面是禁止使用拷贝构造函数和赋值操作符,这需要//C++11的支持thread_guard(thread_guard const&)=delete;thread_guard& operator=(thread_guard const&)=delete;};struct func;void f(){int some_local_state=0;func my_func(some_local_state);std::thread t(myfunc);thread_guard g(t);do_something_in_current_thread();}上面的原理是局部变量会按照构造的逆顺序销毁,因为这些变量都在栈上。thread_guard对象g首先销毁,在它的析构函数调用了join()。
上面代码中禁用了复制构造函数和赋值操作符。这是为了防止thread_guard对象超出thread对象的生命周期。
如果不需要等待线程终止,那么可以用分离来避免异常安全问题。
在后台运行线程
在线程对象调用detach()后,线程就分离了,在后台运行了,没有直接的方法了和它通信了。线程在后台运行后,控制权就交给了C++ Runtime Library,来保证当线程存在时资源的回收使用。
分离的线程叫做守护线程,这个来源于Unix中的守护进程(在后台运行,没有显示的用户接口)。这样的线程常常是长时间运行的,它们经常在应用的整个生命周期都在运行,清理不使用的对象或者优化数据结构等。另一种极端情况是,它可以使用分离的线程(如果有一种机制可以检测某个线程是否完成任务,或线程是用来即发即弃任务“fire and forget”)。
在分离一个线程前,必须确保线程可以分离,即std:thread的对象还和线程关联。和调用join()前的检查相同,先调用joinable(),如果返回true,再调用detach。
考虑一个文件处理的应用。这个应用可以同时编辑多个文档。编辑窗口是独立的,它们的代码相同,但是处理的数据不同。一种处理的方法就是在打开一个新的文档时就创建新的线程,然后分离。
void edit_document(std::string const& filename){open_document_and_display_gui(filename);while(!done_editing())//编辑是否完成{user_command cmd=get_user_input();//用户输入命令if(cmd.type==open_new_document)//要打开新文档{std::string const new_name=get_filename_from_user();std::thread t(edit_document,new_name);//创建线程t.detach();//分离,在后台运行}else{process_user_input(cmd);}}}
0 0
- 管理线程之等待线程结束
- 等待指定线程结束
- 等待线程结束
- pthread_join(等待另一个线程结束)
- 安全的等待线程结束
- 等待一个线程的结束
- 线程结束等待与线程优先级
- Win32多线程之等待一个线程的结束(WaitForSingleObject)
- c++11线程管理,RAII方式等待异常环境下线程结束
- 初识pthread(一)-线程管理之创建/结束线程
- VC++等待线程结束的方法
- 主线程等待子线程执行结束
- Java如何等待子线程执行结束
- Java如何等待子线程执行结束
- Java如何等待子线程执行结束
- 等待线程结束的高手--WaitForSingleObject
- Java如何等待子线程执行结束
- Java如何等待子线程执行结束
- mysql中limit用法
- PHP中include与require函数的区别
- Html.RenderPartial使用三个参数
- C++模板特化
- wordpress/wp-admin目录文件
- 管理线程之等待线程结束
- 测试
- 如何选择Html.RenderPartial和Html.RenderAction
- 原VB封装的命名空间Microsoft.VisualBasic的妙用(方便,实用,高效,快速)
- 变态最大值
- iOS 8 UITableViewCell 分割线 左对齐
- 一、v4l2文档之——v4l2 framework
- 好帖摘录
- 向数据库查询或者更改String类型数据的问题