丹东建设安全监督网站,太原网站建设制作,郑州网络公司排名,咖啡建设网站的目的C多线程并发编程入门#xff08;目录#xff09;
本文用最简单易懂的实际案例#xff0c;讲清楚了 join 的实际内涵#xff0c;保证你过目不忘。
Hello join 示例
join 函数是我们接触C多线程 thread 遇到的第一个函数。
比如#xff1a;
int main()
{thread t(f);t.…C多线程并发编程入门目录
本文用最简单易懂的实际案例讲清楚了 join 的实际内涵保证你过目不忘。
Hello 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 就要等到最后。
比如
int main()
{thread t1(f1);t1.join();thread t2(f2);t2.join();
}
假如 f1 需要执行5秒 f2 需要执行 1 秒 那么 main 就需要等待 max(5, 1) 5 秒。
整个过程中 f1 f2 各自独立运行谁运行谁的互不干涉。
执行示意图 完整示例
下面的代码main 线程 等待 first 线程 和 second 线程都退出之后再退出。
#include iostream
#include thread
#include chrono
using namespace std;
using namespace std::chrono;void first()
{// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(5));cout first finished! endl;
}void second()
{// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(1));cout second finished! endl;
}int main()
{auto start std::chrono::system_clock::now();std::cout starting first helper...\n;std::thread helper1(first);std::cout starting second helper...\n;std::thread helper2(second);std::cout waiting for helpers to finish... std::endl;helper1.join();helper2.join();auto elapsed chrono::duration_castchrono::seconds(system_clock::now() - start).count();std::cout done! elapsed elapsed seconds.;
}执行结果 main 等待所有线程的退出 可以看出main 确实是等待两个线程都执行完之后才退出的。
有一个细节 先执行完了 second 线程后执行完了 first 线程。
这样很正常 毕竟 second 线程耗时短1秒first 线程耗时长5秒。
所以main 等待了 5 秒钟才退出。
线程的嵌套join的弊端
实际工作中我们创建线程不大可能都在 main 函数中创建。
我们通常是在其他线程中遇到了某种事件发生这时候才知道要赶紧创建新的线程来执行某个新任务。
比如我们写了一个腾讯会议软件点击开始录制按钮的时候创建录制线程。
录制按钮的回调函数是在UI线程里执行的也就是创建录制线程并执行录制现场这件事发生在UI线程里。不在main线程里。
示例
int main()
{thread ui(ui_fun);ui.join();//main等待整个窗口程序关闭再退出
}ui_fun()
{thread button_clicked(on_button_clicked);//创建录制线程button_clicked.join();//执行录制动作
}
这种情况main 等待 ui 线程这没什么问题。但是 ui 等待 录制线程就会导致 ui 线程卡住。
此时你按界面上其他的按钮就不会有任何响应。这是不应该发生的。
执行示意图 main一共等待了156秒 完整示例
#include iostream
#include thread
#include chrono
using namespace std;
using namespace std::chrono;void record()
{// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(1));cout record finished! endl;
}void ui_fun()
{std::cout starting record ...\n;std::thread record_thread(record);record_thread.join();// simulate expensive operationstd::this_thread::sleep_for(std::chrono::seconds(5));cout ui_fun finished! endl;
}int main()
{auto start std::chrono::system_clock::now();std::cout starting ui_fun ...\n;std::thread helper1(ui_fun);std::cout waiting for ui_fun to finish... std::endl;helper1.join();auto elapsed chrono::duration_castchrono::seconds(system_clock::now() - start).count();std::cout done! elapsed elapsed seconds.;
}执行结果 参考
C std::thread join()的理解 - 代萌 - 博客园 (cnblogs.com)
std::thread::join - cppreference.com