C++11多线程基础
2021/7/12 20:35:58
本文主要是介绍C++11多线程基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. join
#include <iostream> #include <thread> using namespace std; void fun() //子线程 { for (int i = 0; i < 100; i++) cout << "*"; } void main() { thread t(fun); //创建线程,线程从fun()函数开始执行 t.join(); //阻塞主线程,让主线程等待子线程执行完毕 for (int i = 0; i < 100; i++) //主线程 cout << "$"; }
输出:****************************************************************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include <iostream> #include <thread> using namespace std; void fun() //子线程 { for (int i = 0; i < 100; i++) cout << "*"; } void main() { thread t(fun); //创建线程,线程从fun()函数开始执行 for (int i = 0; i < 100; i++) //主线程 cout << "$"; t.join(); //阻塞主线程,让主线程等待子线程执行完毕 }
输出:
*****************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*******************$$$$$$$$$*************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$***
#include <iostream> #include <thread> using namespace std; void fun() //子线程 { for (int i = 0; i < 100; i++) cout << "*"; } void main() { thread t(fun); //创建线程,线程从fun()函数开始执行 for (int i = 0; i < 100; i++) //主线程 cout << "$"; }
输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16$$ 17$$ 18 19 20 21 22 23 24 25 26 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$27
2. detach
#include <iostream> #include <thread> using namespace std; void fun() //子线程 { for (int i = 0; i < 100; i++) cout << i << " "; } void main() { thread t(fun); //创建线程,线程从fun()函数开始执行 t.detach(); //主线程不等待子线程执行完毕就可以先行退出,子线程驻留在后台运行 for (int i = 0; i < 100; i++) //主线程 cout << "$"; }
输出:
0 1 2 3 4 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$5
3. joinable
#include <iostream> #include <thread> using namespace std; void fun() //子线程 { for (int i = 0; i < 100; i++) cout << i << " "; } void main() { thread t(fun); //创建线程,线程从fun()函数开始执行 if (t.joinable()) //判断是否可以成功使用join()或者detach(),调用join后不能再调用join和detach,调用detach后也不能再调用join和detach。因为重复调用会导致异常 { t.join(); cout << "joinable() == true" << endl; } for (int i = 0; i < 100; i++) //主线程 cout << "$"; }
输出:****************************************************************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
4. 可调用对象
#include <iostream> #include <thread> using namespace std;class A { public: void operator()() //不能带参数 { for (int i = 0; i < 100; i++) //子线程 cout << i << " "; } }; void main() { A a; //a:可调用对象 thread t(a); //将对象a复制到子线程中,执行完主线程后,对象a会被销毁,但是复制到子线程中的对象依旧存在。只要这个A类对象没有主线程中的引用或指针,就不会出现问题。 t.join(); //阻塞主线程,让主线程等待子线程执行完毕 for (int i = 0; i < 100; i++) //主线程 cout << "$"; }
输出:****************************************************************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
5.lambda表达式
#include <iostream> #include <thread> using namespace std;void main() { auto lamthread = [] { for (int i = 0; i < 100; i++) cout << i << " "; }; thread t(lamthread); t.join(); }
输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
6. 陷阱
#include <iostream> #include <thread> using namespace std; void fun(const int& i, char* buf) //子线程 { cout << i << endl; cout << buf << endl; } void main() { int num = 9; char buf[] = "abc"; thread t(fun, num, buf); t.join(); cout << "i love you" << endl; }
输出:
9
abc
i love you
#include <iostream> #include <thread> using namespace std; void fun(const int& i, char* buf) //子线程 { cout << i << endl; //i并不是num的引用,实际是值传递。即使主线程使用detach,子线程中的i也是安全的。最好不使用引用。 cout << buf << endl; //指针在主线程使用detach时,绝对会有问题。因为主线程中的buf已经被释放,所以子线程中的buf就变成了野指针。 } void main() { int num = 9; char buf[] = "abc"; thread t(fun, num, buf); //有问题 t.detach(); }
#include <iostream> #include <thread> using namespace std; void fun(const int& i, string& buf) //子线程 { cout << i << endl; cout << buf.c_str() << endl; } void main() { int num = 9; char buf[] = "abc"; thread t(fun, num, string(buf)); //没问题。用临时构造的string类对象作为参数传递给线程,一定能在主线程执行完毕前把线程函数的第二个参数构造出来,从而确保主线程即便detach了子线程也能安全运行。
t.detach(); }
#include <iostream> #include <thread> using namespace std; class A { public: //类型转换构造函数,可以把一个int转换成一个类A对象 A(int i) :m_i(i) { cout << "调用构造函数" << this << endl; } A(const A& a) :m_i(a.m_i) { cout << "调用拷贝构造函数}" << this << endl; } A() { cout << "调用析构函数" << this << endl; } private: int m_i; }; void fun(const int& i, const A& a) //子线程 { cout << i << endl; cout << &a << endl; //输出对象地址 } void main() { int num = 9;int sum = 0; thread t(fun, num, sum); //有时候都还没调用构造函数主线程就退出了,则会有问题。需要改成创建临时对象thread t(fun, num, A(sum)); t.detach(); }
#include <iostream> #include <thread> using namespace std; class A { public: //类型转换构造函数,可以把一个int转换成一个类A对象 A(int i) :m_i(i) { cout << "调用构造函数" << this << endl; } A(const A& a) :m_i(a.m_i) { cout << "调用拷贝构造函数}" << this << endl; } A() { cout << "调用析构函数" << this << endl; } private: int m_i; }; void fun(const int& i, const A& a) //子线程 { cout << i << endl; cout << &a << endl; //输出对象地址 } void main() { int num = 9;int sum = 0; thread t(fun, num, A(sum)); //绝对没问题。绝对在先调用构造函数后再退出主线程 t.detach(); }
输出:
调用构造函数00ADF884
调用拷贝构造函数}00E54B58
9
8. 线程id
验证:
#include <iostream> #include <thread> using namespace std; class A { public: //类型转换构造函数,可以把一个int转换成一个类A对象 A(int i) :m_i(i) { cout << "调用构造函数" << this << " threadid:" << std::this_thread::get_id() << endl; } A(const A& a) :m_i(a.m_i) { cout << "调用拷贝构造函数}" << this << " threadid:" << std::this_thread::get_id() << endl; } A() { cout << "调用析构函数" << this << " threadid:" << std::this_thread::get_id() << endl; } private: int m_i; }; void fun(const A& a) //子线程 { cout << "a threadid:" << std::this_thread::get_id() << endl; cout << &a << endl; //输出对象地址 } void main() { cout << "主线程id:" << std::this_thread::get_id() << endl; int num = 9;int sum = 0; thread t(fun, sum); //在子线程中构造的A类对象。当调用detach时显然会出问题,因为sum已释放,则子线程中的sum就是不可预知的值。 t.join(); }
输出:
主线程id:5300
调用构造函数00CCF7E4 threadid:6380
a threadid:6380
00CCF7E4
#include <iostream> #include <thread> using namespace std; class A { public: //类型转换构造函数,可以把一个int转换成一个类A对象 A(int i) :m_i(i) { cout << "调用构造函数" << this << " threadid:" << std::this_thread::get_id() << endl; } A(const A& a) :m_i(a.m_i) { cout << "调用拷贝构造函数}" << this << " threadid:" << std::this_thread::get_id() << endl; } A() { cout << "调用析构函数" << this << " threadid:" << std::this_thread::get_id() << endl; } private: int m_i; }; void fun(const A& a) //子线程。 用引用传递,否则得多调用一次拷贝构造函数 { cout << "a threadid:" << std::this_thread::get_id() << endl; cout << &a << endl; //输出对象地址 } void main() { cout << "主线程id:" << std::this_thread::get_id() << endl; int num = 9; int sum = 0; thread t(fun, A(sum)); //在主线程中构造的A类对象。当调用detach时也不会有问题。 t.join(); }
输出:
主线程id:18328
调用构造函数003CF874 threadid:18328
调用拷贝构造函数}0043AD88 threadid:18328
a threadid:14056
0043AD88
8.
这篇关于C++11多线程基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-19WebSocket入门指南:轻松搭建实时通信应用
- 2024-11-19Nacos安装资料详解:新手入门教程
- 2024-11-19Nacos安装资料:新手入门教程
- 2024-11-19升级 Gerrit 时有哪些注意事项?-icode9专业技术文章分享
- 2024-11-19pnpm是什么?-icode9专业技术文章分享
- 2024-11-19将文件或目录压缩并保留到指定的固定目录怎么实现?-icode9专业技术文章分享
- 2024-11-19使用 tar 命令压缩文件并且过滤掉某些特定的目录?-icode9专业技术文章分享
- 2024-11-18Nacos安装入门教程
- 2024-11-18Nacos安装入门:轻松掌握Nacos服务注册与配置管理
- 2024-11-18Nacos配置中心入门:新手必读教程