C++多线程并发编程入门(目录)
本文用最简单易懂的实际案例,讲清楚了 join 的实际内涵,保证你过目不忘。
join 函数是我们接触C++多线程 thread 遇到的第一个函数。
比如:
int main()
{
thread t(f);
t.join();
}
join 表示线程 t 运行起来了。但是,t 也阻碍了 main 线程的退出。
也就是说,如果 f 的执行需要 5秒钟, main也要等待5秒才能退出。
这看起来非常合理,因为 main 就应该等待 t 退出之后再退出。
多个线程都以 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
#include
#include
using namespace std;
using namespace std::chrono;
void first()
{
// simulate expensive operation
std::this_thread::sleep_for(std::chrono::seconds(5));
cout << "first finished!" << endl;
}
void second()
{
// simulate expensive operation
std::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_cast(system_clock::now() - start).count();
std::cout << "done! elapsed "<
执行结果
可以看出,main 确实是等待两个线程都执行完之后才退出的。
有一个细节, 先执行完了 second 线程,后执行完了 first 线程。
这样很正常, 毕竟 second 线程耗时短(1秒),first 线程耗时长(5秒)。
所以,main 等待了 5 秒钟才退出。
实际工作中,我们创建线程不大可能都在 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 线程卡住。
此时你按界面上其他的按钮,就不会有任何响应。这是不应该发生的。
#include
#include
#include
using namespace std;
using namespace std::chrono;
void record()
{
// simulate expensive operation
std::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 operation
std::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_cast(system_clock::now() - start).count();
std::cout << "done! elapsed " << elapsed << " seconds.";
}
执行结果
C++ std::thread join()的理解 - 代萌 - 博客园 (cnblogs.com)
std::thread::join - cppreference.com