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两者只能使用其中的一个,并且只能一次。

 

posted @ 2020-06-26 21:06  sunshine_gzw  阅读(187)  评论(0编辑  收藏  举报