• Thread线程框架学习


    原文:https://www.cnblogs.com/wangkeqin/p/9351299.html

    Thread线程框架

    线程定义:
    线程可以理解为一个特立独行的函数。其存在的意义,就是并行,避免了主线程的阻塞。

    ----------------------------thread与函数----------------------------------

    线程启动

      C++线程的启动, 只需要#include <thread>即可。 线程对象的创建, 意味着线程的开始。

    1)同步

    复制代码
    #include <iostream>
    #include <thread>
    #include <unistd.h>
    
    using namespace std;
    
    void func()
    {
        cout<<"thread id:"<<this_thread::get_id()<<endl;
        cout<<"do some work"<<endl;
        sleep(3);
    } 
    int main()
    {
        cout<<"maint thread id:"<<this_thread::get_id()<<endl;
        thread t(func);
        t.join();
        return 0;
    }
    复制代码

      t.join 和 t.detach 标志着, 线程对象和线程的关系。 t.join 表示, 线程与线程对象的同步关系。 而 t.detach 表示, 线程与线程对象的异步关系。 在线程生成后,必须指定join或者detach状态来。

      detach 后的线程,不能再 join,是否可以 join 可以通过 joinable 来判断。 

    2)异步

    复制代码
    #include <iostream>
    #include <memory>

    using namespace std; void func() { cout<<"thread id:"<<this_thread::get_id()<<endl; int i = 0; while(i++<5) { cout<<"assist thread running times:"<<i<<endl; sleep(1); } cout<<"----end assist thread work!------"<<endl; } int main() { cout<<"maint thread id:"<<this_thread::get_id()<<endl; thread t(func); // t.join(); //!同步 t.detach(); //!异步 int i =0; while(i++<10) { cout<<"main thread running times:"<<i<<endl; sleep(1); } cout<<"-----main thread finished!-----"<<endl; }
    复制代码

      在次线程detach的状态下,要保证主线程的上声明周期要比次线程声明周期长,否则此线线程将中断退出。

    传参方式

      线程有自己独立的栈。可供享受全局的变量。在线程启动的时候可以传入启动的参数。

    复制代码
    #include <iostream>
    #include <thread>
    using namespace std;
    
    void func(int n, string s)
    {
        for(int i=0;i <n ;i++)
        {
            cout<<s<<endl;
        }
    }
    int main()
    {
        thread t(func,5,"china");
        t.join();
        return 0;
    }
    复制代码

      除了传入参数,共享全局以外,还可以使用std::ref辅助传入本地变量的引用。thread认为不加std::ref包装的变量都是以拷贝的方式传入线程中去的。

    复制代码
    #include <iostream>
    #include <thread>
    using namespace std;
    
    void func(int &n, string &s)
    {
        for(int i=0;i <n ;i++)
        {
            cout<<s<<endl;
        }
        n = 10;
        s = "america";
    }
    
    int main()
    {
        int n = 5;
        string s = "china";
    //    thread t(func,n, s);          //!编译不过,thread无法区分传入的参数
        thread t(func,ref(n), ref(s));        //!正确的传引用的姿势,应该采用std::ref来对变量包装
        t.join();
        return 0;
    
    复制代码

     

    ----------------------------thread与类成员函数-----------------------------------

      以上都是通过线程来包装普通的函数。类的成员函数该如何引入线程呢?如下:

    1)类外使用线程(推荐):

    复制代码
    #include <iostream>
    #include <thread>
    
    using namespace std;
    
    class ThreadTest
    {
    public:
        ThreadTest()
        {
            cout<<"ThreadTest():"<<this<<endl;
        }
        void func()
        {
            int n = 0;
            cout<<"void func(int n):"<<this<<endl;
            while(n++<10)
            {
                cout<<"thread in class runtime:"<<n<<endl;
            }
        }
        ~ThreadTest() = default;
    };
    
    
    int main()
    {
        ThreadTest test;
        thread t(&ThreadTest::func,test);
        t.join();
        cout<<"Pls observe the difference between the two printed addresses!"<<endl;return 0;
    }
    复制代码

      这个函数执行起来显然没什么错误,但是有一个问题:我们构造时对象的内存地址居然与多线程中执行函数地址不一样,要记住这可是该对象的成员函数啊?我们前面已经提到过,不使用std::ref传入线程的变量默认都是以拷贝的方式传入的。两次地址不一样的原因就是如此!要想将该对象的成员函数加入线程,我们应该使用std::ref或者直接传入对象的指针。

    复制代码
    #include <iostream>
    #include <thread>
    
    using namespace std;
    
    class ThreadTest
    {
    public:
        ThreadTest()
        {
            cout<<"ThreadTest():"<<this<<endl;
        }
        void func()
        {
            int n = 0;
            cout<<"void func(int n):"<<this<<endl;
            while(n++<10)
            {
                cout<<"thread in class runtime:"<<n<<endl;
            }
        }
        ~ThreadTest() = default;
    };
    
    
    
    
    int main()
    {
        ThreadTest test;
    //    thread t(&ThreadTest::func,test);             //!对象拷贝
          thread t(&ThreadTest::func,std::ref(test));           //!传入引用
        //   thread t(&ThreadTest::func,&test);         //!传入指针;
        t.join();
        cout<<"Please observe the difference between the two printed addresses!"<<endl;return 0;
    }
    复制代码

    2)类内使用线程:

    复制代码
    #include <iostream>
    #include <thread>
    using namespace std;
    
    
    class ThreadInClass
    {
    public:
        ThreadInClass(){cout<<"ThreadInClass():"<<this<<endl;}
        ~ThreadInClass() = default;
        void runThread()
        {
            thread t(&ThreadInClass::func,this);
            t.join();
    //        t.detach();//使用detach,同样也要保证runThread的生存周期比t要长。
        }
        void func()
        {
            int n = 0;
            cout<<"void func(int n):"<<this<<endl;
            while(n++<10){
                cout<<"thread in class runtime:"<<n<<endl;
            }
        }
    };
    
    int main()
    {
        ThreadInClass tic;
        tic.runThread();
    }
    复制代码
  • 相关阅读:
    NestingQuery
    Repeat
    GenericQuery
    StringOpr
    RHEL5.6 安装 virtualbox
    DNS的资料总结
    drop delete truncate 区别
    Linux Shell命令ulimit的用法
    OSI及TCP/IP的概念和区别
    shell:读取文件的每一行内容并输出
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/11672955.html
Copyright © 2020-2023  润新知