Loading... # 一、使用多线程的场景 任务分解:耗时的操作,任务分解,实时响应 数据分解:充分利用多核 CPU 处理数据 数据流分解:读写分离,解耦合设计 # 二、C++ 11 多线程快速入门 ## 1. 先动手写第一个 c++11 多线程程序 ```cpp #include <iostream> #include <thread> using namespace std; using namespace chrono; using namespace this_thread; // 线程入口函数 void ThreadMain() { cout << " 进入子线程" << get_id() << endl; for (int i = 0; i < 10; i++) { cout << "in thread id = " << i << endl; sleep_for(seconds(1)); // 线程释放 cpu 资源 1 秒 } cout <<get_id()<< " 线程退出" << endl; } // 主线程入口 int main(int argc, char* argv[]) { cout << "主线程ID "<< get_id() << endl; //1 创建并启动子线程 , 进入线程函数 thread th(ThreadMain); cout << "等待子线程退出" << endl; th.join(); cout << "等待主线程返回" << endl; return 0; } peter@iZbp1aq6c9kbbder4q405mZ:~/test/threadTopic/xiahoujun_class_demo/dierzhang$ g++ 2_1.cpp -o 2_1 -std=c++11 -lpthread peter@iZbp1aq6c9kbbder4q405mZ:~/test/threadTopic/xiahoujun_class_demo/dierzhang$ ./2_1 主线程ID 140641257162560 等待子线程退出 进入子线程140641257158400 in thread id = 0 in thread id = 1 in thread id = 2 in thread id = 3 in thread id = 4 in thread id = 5 in thread id = 6 in thread id = 7 in thread id = 8 in thread id = 9 140641257158400 线程退出 等待主线程返回 ``` 分析: 1. 如果是多核的情况下 cout << "等待子线程退出" << endl; 和 cout << " 进入子线程" << get\_id() << endl; 之间的打印可能存在交替 2. 使用sleep\_for(seconds(1)); 可以让资源得到释放 3. th.join();等待子线程退出 ## 2. 测试生命周期代码 ```cpp // 线程入口函数 bool is_exit = false; void ThreadMain() { while(!is_exit) { cout<<"ThreadMain"<<endl; //this_thread::sleep_for(100ms); this_thread::sleep_for(chrono::milliseconds(100)); } } // 主线程入口 int main(int argc, char* argv[]) { //1 创建并启动子线程 , 进入线程函数 { thread th(ThreadMain);//// 出错 线程句柄清理 , 线程还在运行 } return 0; } peter@iZbp1aq6c9kbbder4q405mZ:~/test/threadTopic/xiahoujun_class_demo/dierzhang$ g++ 2_2.cpp -o 2_2 -std=c++11 -lpthread peter@iZbp1aq6c9kbbder4q405mZ:~/test/threadTopic/xiahoujun_class_demo/dierzhang$ ./2_2 terminate called without an active exception Aborted (core dumped) ``` 分析: thread th对象被销毁,但是子线程还在运行。 打开core文件的堆栈 ```cpp peter@iZbp1aq6c9kbbder4q405mZ:~/test/threadTopic/xiahoujun_class_demo/dierzhang$ gdb 2_2 core GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from 2_2... (No debugging symbols found in 2_2) [New LWP 2290765] [New LWP 2290766] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Core was generated by `./2_2'. Program terminated with signal SIGABRT, Aborted. #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. [Current thread is 1 (Thread 0x7fd77e71d740 (LWP 2290765))] (gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 #1 0x00007fd77e896859 in __GI_abort () at abort.c:79 #2 0x00007fd77eb1c951 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6 #3 0x00007fd77eb2847c in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6 #4 0x00007fd77eb284e7 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6 #5 0x00005593c815649d in std::thread::~thread() () #6 0x00005593c8156397 in main () (gdb) f 5 #5 0x00005593c815649d in std::thread::~thread() () (gdb) f 6 #6 0x00005593c8156397 in main () (gdb) ``` 可以查看thread::\~thread()内部源码看下怎么实现的 ```jsx ~thread() { if (joinable()) std::terminate(); } ``` 解决办法: ```cpp { //解决办法1: 主线程等待子线程退出 缺点:但是这样的话主线程就啥事也做不了了 thread th(ThreadMain); th.join(); // 等待子线程 , 主线程阻塞 } { //解决办法2:主线程和子线程同时运行,又不想维护th这个对象,那么可以让主线程和子线程分离 缺点:主线程退出后,子线程不一定退出 thread th(ThreadMain); th.detach(); // 子线程分离 } ``` 针对解决办法2,如果主线程退出后[全局空间以及栈上的空间释放掉了],子线程没有退出的话,而且此时子线程有访问到主线程中释放额一些资源,就会导致程序异常coredump。比如实际场景中,当你关闭窗口的时候,又弹出了一个窗口。 怎么解决**解决办法2**中遇到的问题, 方案A、如果detach掉了一个子线程,这个子线程就不要再访问外部变量,只访问线程内部声明的变量 方案B、主线程退出之后,通知下子线程,子线程自己去退出。 方案B的demo: ```cpp #include <iostream> #include <thread> using namespace std; using namespace chrono; using namespace this_thread; // 线程入口函数 bool is_exit = false; void ThreadMain() { while(!is_exit) { cout<<"ThreadMain"<<endl; //this_thread::sleep_for(100ms); this_thread::sleep_for(chrono::milliseconds(100)); } } // 主线程入口 int main(int argc, char* argv[]) { { //解决办法3: thread th(ThreadMain); this_thread::sleep_for(chrono::milliseconds(100)); is_exit = true; cout << "主线程阻塞,等待子线程退出"<< endl; th.join(); // 等待子线程 , 主线程阻塞 cout << "子线程已经退出" <<endl; } return 0; } ``` 设置一个标志位,当主线程要退出时,通知子线程 is\_exit = true; 最后修改:2025 年 07 月 02 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏