本文用最简单易懂的实际案例,讲清楚了 join 的实际内涵,保证你过目不忘。
示例
join 函数是我们接触C++多线程 thread 遇到的第一个函数。
比如:
int main()
{
thread t(f);
t.join();
}
join 用来阻塞当前线程退出
join 表示线程 t 运行起来了。但是,t 也阻碍了 main 线程的退出(谁调用,阻塞谁)。
也就是说,如果 f 的执行需要 5秒钟, main也要等待5秒才能退出。
这看起来非常合理,因为 main 就应该等待 t 退出之后再退出。
main 等待所有线程
多个线程都以 join 的方式启动的时候,main 就要等到最后。
比如:
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <chrono>
using namespace std;
using namespace chrono;
auto start = system_clock::now();
void print_elapsed(string msg)
{
cout << msg << " at[" << duration_cast<milliseconds>(system_clock::now()-start).count()<<"]" << endl;
}
void task_fun(int i)
{
print_elapsed("task_fun " + to_string( i) + " start!");
// simulate expensive operation
this_thread::sleep_for(seconds(i));
print_elapsed("task_fun " + to_string(i) + " finished!");
}
int main()
{
print_elapsed( "main begin...");
thread task1(task_fun, 9);//线程这时候就已经开始启动
thread task2(task_fun, 6);//线程这时候就已经开始启动
thread task3(task_fun, 3);//线程这时候就已经开始启动
thread task4(task_fun, 12);//线程这时候就已经开始启动
print_elapsed("waiting for all tasks to finish...");
task1.join();//main第一次阻塞,给前面的线程机会执行到各自打印的语句
print_elapsed("task1.join() finished");//第9秒钟之后,main终于等到了task1的退出,在这之前task3(第3秒执行完毕),task2(第6秒),执行完毕
task2.join();//这里不会有阻塞,因为在第6秒的时候task2就已经退出了
print_elapsed("task2.join() finished");
task3.join();//这里不会有阻塞,因为在第3秒的时候task2就已经退出了
print_elapsed("task3.join() finished");
task4.join();//这里会再次阻塞3秒(从第9秒阻塞到第12秒)
print_elapsed("task4.join() finished");
print_elapsed("all tasks to finished.");
}