zoukankan      html  css  js  c++  java
  • 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.  

  • 相关阅读:
    队列(顺序存储结构)
    2015计划
    iframe子窗口父窗口方法调用和元素获取
    Ajax关于重定向
    Java国际化资源文件的选择
    eclipse自动部署web应用程序到tomcat webapps
    从给定字符串结尾获取指定字节长度的字符串
    Winform的一些不知道啥东西
    C# 2008核心编程 2013-09-14
    C# 2008核心编程 2013-09-10
  • 原文地址:https://www.cnblogs.com/tingtaishou/p/15003770.html
Copyright © 2011-2022 走看看