1. 等待线程完成
若不等待线程完成,我们就需要确保该线程访问的数据都是有效的,直到该线程完成为止。比如如下代码,线程函数持有局部变量的指针或引用,当函数退出时,线程尚未执行完成。
#include <thread>
#include <iostream>
// 线程持有局部变量的指针
struct func
{
int *i;
func(int *i_) : i(i_){
}
void operator()()
{
for (unsigned j = 0; j < 100000; ++j)
{
*i = j; // 访问非法地址
}
}
};
// 不等待线程执行完成就退出
void oops()
{
int some_local_state = 0;
func my_func(&some_local_state);
std::thread my_thread(my_func);
my_thread.detach();
}
int _tmain(int argc, _TCHAR* argv[])
{
oops();
return 0;
}
要避免这种情况,需要使用std::thread实例的join()来替换my_thread.detach()的调用,这样就可以保证在函数退出前,线程已经结束。对一个给定的线程,只能调用一次join(),一旦调用了join(),此std::thread对象不再是可连接的,如果调用其的joinable()将返回false。
2. 在异常环境下的等待
我们需要在线程对象被销毁前调用join或detach方法,如果要detach,通常在线程启动后就立即调用detach方法。如果打算等待该线程,就