C++线程基础笔记(一)
标准写法:
#include<iostream> #include<thread> using namespace std; void MyThread() { cout << "MyThread线程1开始了" << endl; cout << ".................." << endl; cout << "MyThread线程1结束了" << endl; } int main() { thread my(MyThread); my.join(); cout<<"主线程开始了"<< endl; cout<<"............."<< endl; cout<<"主线程结束了"<< endl; return 0; }
输出结果:
分析:
首先利用可调用对象MyThread创建了子线程my;
然后调用类thread的函数join,表示只有当我的子线程结束了,主线程才可以结束;说白了它的作用就是用来堵塞主线程的.
如果不加join函数,那么主进程和子进程就会同时执行,不分先后,如果子线程还没结束主线程就结束了,那么系统会抛出异常,如下代码:
#include<iostream> #include<thread> using namespace std; void MyThread() { cout << "MyThread线程1开始了" << endl; cout << ".................." << endl; cout << "MyThread线程1结束了" << endl; } int main() { thread my(MyThread); //my.join(); cout<<"主线程开始了"<< endl; cout<<"............."<< endl; cout<<"主线程结束了"<< endl; return 0; }
输出:
如果我就想让主线程先退出,但是不抛出异常,那么可以用detach(),如下代码:
#include<iostream> #include<thread> using namespace std; void MyThread() { cout << "MyThread线程1开始了" << endl; cout << ".................." << endl; cout << "MyThread线程1结束了" << endl; } int main() { thread my(MyThread); my.detach(); cout<<"主线程开始了"<< endl; cout<<"............."<< endl; cout<<"主线程结束了"<< endl; return 0; }
输出:
对于使用detach(),存在许多隐患,比如:
#include<iostream> #include<thread> using namespace std; class MyThread { public: int &x; MyThread(int &_x):x(_x) {} void operator()() { cout << "子线程开始执行了" << endl; cout << "x的值是:" << x << endl; cout << "..............." << endl; cout << "子线程结束了" << endl; } }; int main() { int data = 1;
MyThread myobj(data); thread my(myobj); my.detach(); cout<<"主线程开始了"<< endl; cout<<"............."<< endl; cout<<"主线程结束了"<< endl; return 0; }
输出:
分析:
1.这里造成的原因主要就是因为我的类中含有引用,对于刚开始用int data=1生成的变量,main结束后(主线程结束),data就会消失,由于我使用了detach,所以主线程和子线程谁先谁后结束不确定,如果主线程先结束了,data也会跟着消失,子线程再去访问该数据便会无从寻起。
基于此,可能连带产生如下困惑,如下两行代码:
MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②
如果主线程先结束,那么myobj对象一同消失,那么②的代码中的myobj不也会消失吗?
为了解答这个问题,做如下实验:
#include<iostream> #include<thread> using namespace std; class MyThread { public: int &x; MyThread(int &_x):x(_x) {} MyThread(const MyThread& another):x(another.x) { cout << "拷贝构造函数被执行" << endl; } ~MyThread() { cout << "析构函数被执行" << endl; } void operator()() { cout << "子线程开始执行了" << endl; cout << "x的值是:" << x << endl; cout << "..............." << endl; cout << "子线程结束了" << endl; } }; int main() { int data = 1; MyThread myobj(data); thread my(myobj); my.detach(); cout<<"主线程开始了"<< endl; cout<<"............."<< endl; cout<<"主线程结束了"<< endl; return 0; }
输出:
以上代码只有thread my(myobj); 这一句才有可能发生拷贝构造.
所以对于:
MyThread myobj(data);。。。。。。。。。。。。①
thread my(myobj); .。。。。。。。。。。。。。。②
①到②会发生拷贝构造,图的运行结果就是证明。
如果join或者detach其中一个已被使用,那么就不能再次被使用,
类库提供了一个joinable函数可以判断是否已被使用,看如下代码:
1 #include<iostream> 2 #include<thread> 3 using namespace std; 4 class MyThread 5 { 6 public: 7 int &x; 8 MyThread(int &_x):x(_x) {} 9 MyThread(const MyThread& another):x(another.x) 10 { 11 12 cout << "拷贝构造函数被执行" << endl; 13 } 14 ~MyThread() 15 { 16 cout << "析构函数被执行" << endl; 17 } 18 void operator()() 19 { 20 21 cout << "子线程开始执行了" << endl; 22 cout << "x的值是:" << x << endl; 23 cout << "..............." << endl; 24 cout << "子线程结束了" << endl; 25 } 26 }; 27 28 int main() 29 { 30 int data = 1; 31 MyThread myobj(data); 32 thread my(myobj); 33 my.join(); 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。① 34 if (my.joinable()) 35 { 36 cout << "join或者detach可以被使用" << endl; 37 } 38 else 39 { 40 cout << "join或者detach已经被用" << endl; 41 } 42 my.detach();。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。② 43 if (my.joinable()) 44 { 45 cout << "join或者detach可以被使用" << endl; 46 } 47 else 48 { 49 cout << "join或者detach已经被用" << endl; 50 } 51 cout<<"主线程开始了"<< endl; 52 cout << "..............." << endl; 53 cout << "主线程结束了" << endl; 54 55 return 0; 56 }
对①和②插入断点进行调试:
第一次进入了if语句,继续调试:
当执行第二个时候发生了异常。
继续实验:
更加证实了前面的观点,join或者detach两者只能使用其中的一个,并且只能一次。