· join():主线程等待该线程结束,然后继续执行。一旦已经使用过join(),相应的 std::thread 对象就与实际执行的线程无关了, std::thread 对象就不能再次加入了。
· detach():不等待线程结束,继续往下执行。线程还在继续执行。
· std::thread 对象使用t.joinable()返回的是true,就可以使用t.detach()。调用 std::thread 成员函数detach()来分离一个线程之后,相应的 std::thread 对象就与实际执行的线程无关了,并且这个线程也无法加入。
· 传参启动线程的方法:不仅可以向 std::thread 构造函数①传递函数名,还可以传递函数所需的参数(实参)。
///参数转为引用的形式
void update_data_for_widget(widget_id w,widget_data& data); // 1
void oops_again(widget_id w)
{
widget_data data;
std::thread t(update_data_for_widget,w,data); // 2
display_status();
t.join();
process_widget_data(data); // 3
}
虽然update_data_for_widget①的第二个参数期待传入一个引用,但是 std::thread 的构造函数②并不知晓;构造函数无视函数期待的参数类型,并盲目的拷贝已提供的变量。当线程调用update_data_for_widget函数时,传递给函数的参数是data变量内部拷贝的引用,而非数据本身的引用。因此,当线程结束时,内部拷贝数据将会在数据更新阶段被销毁,且process_widget_data将会接收到没有修改的data变量③。可以使用 std::ref 将参数转换成引用的形式,从而可将线程的调用改为以下形式:std::thread t(update_data_for_widget,w,std::ref(data));
在这之后,update_data_for_widget就会接收到一个data变量的引用,而非一个data变量拷贝的引用。
///
· std::thread::hardware_concurrency() 在新版C++标准库中是一个很有用的函数。这个函数将返回能同时并发在一个程序中的线程数量。