zoukankan      html  css  js  c++  java
  • 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两者只能使用其中的一个,并且只能一次。

  • 相关阅读:
    洛谷P2878 [USACO07JAN]保护花朵Protecting the Flowers
    洛谷P2434 [SDOI2005]区间
    洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn
    洛谷 P2904 [USACO08MAR]跨河River Crossing
    Again Stone Game
    Crazy Calendar (阶梯博弈变形)
    (2017浙江省赛E)Seven Segment Display
    ZOJ 3705 Applications
    D
    The Suspects(并查集维护根节点信息)
  • 原文地址:https://www.cnblogs.com/SunShine-gzw/p/13196373.html
Copyright © 2011-2022 走看看