• 【Linux】多线程_3



    九、多线程

    3. C++11中的多线程

    Linux中是根据多线程库来实现多线程的,C++11也有自己的多线程,那它的多线程又是怎样的?我们来使用一些C++11的多线程。
    Makefile

    testThread: testThread.cc
    	g++ -o $@ $^ -std=c++11
    .PHONY: clean
    clean:
    	rm -f testThread
    

    testThread.cc

    #include 
    #include 
    #include 
    using namespace std;
    
    void threadrun(int num)
    {
        while (num)
        {
            cout << "I am thread, num : " << num << endl;
            sleep(1);
            --num;
        }
    }
    
    int main()
    {
        thread t1(threadrun, 10);
        while (true)
        {
            cout << "I am main thread" << endl;
            sleep(1);
        }
    
        t1.join();
        
        return 0;
    }
    

    编译看看:
    在这里插入图片描述
    我们发现有问题(也可能是其他问题),这是怎么回事呢?其实是 C++11的多线程本质上是对原生线程的封装。所以同样需要链接 phread 动态库。
    Makefile

    testThread: testThread.cc
    	g++ -o $@ $^ -std=c++11 -lpthread
    .PHONY: clean
    clean:
    	rm -f testThread
    

    我们再试试:
    在这里插入图片描述
    确实大部分其编程语言的多线程都是对原生线程的封装,原因是为了可移植性。
    我们在进程部分学过 非阻塞等待 ,进程在等待子进程退出时,可以执行其他任务,在线程这里,同样有这样的技术,叫做线程分离。我们要是不关注线程的结果,只需要线程把自己的任务完成,这种情况就可以将线程进行分离。
    在这里插入图片描述
    Makefile

    testThread: testThread.cc
    	g++ -o $@ $^ -std=c++11 -lpthread
    .PHONY: clean
    clean:
    	rm -f testThread
    

    testThread.cc

    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    void* threadrun(void* args)
    {
        string str = (const char*)args;
        int cnt = 5;
        while (true)
        {
            if (!(cnt--)) break;
            cout << "I am a new thread " << endl;
            sleep(1);
        }
    }
    
    int main()
    {
        pthread_t tid;
        pthread_create(&tid, nullptr, threadrun, (void*)"thread1");
        // 线程分离
        pthread_detach(tid);
    
        while (true)
        {
            cout << "I am the main thread " << endl;
            sleep(1);
        }
    
        return 0;
    }
    

    在这里插入图片描述

    默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
    如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。

    joinable和分离是冲突的,一个线程不能既是joinable又是分离的。如果将线程分离了又对其join,就会出错。
    线程分离底层依旧是属于进程,没有分开,线程分离只是一种状态,唯一的区别就是主线程不需要等待新线程。

    4. 线程的简单封装

    Makefile

    testThread: testThread.cc
    	g++ -o $@ $^ -std=c++11 -lpthread
    .PHONY: clean
    clean:
    	rm -f testThread
    

    Thread.hpp

    #ifndef __THREAD_HPP__
    #define __THREAD_HPP__
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // 线程命名空间
    namespace ThreadModule
    {
        // 线程函数模板
        template<typename T>
        using func_t = std::function<void(T&)>;
    
        // 线程模板
        template<typename T>
        class Thread
        {
        public:
            Thread(func_t<T> func, T data, const std::string& name = "none-name")
            :_func(func)
            ,_data(data)
            ,_threadname(name)
            ,_stop(true)
            {}
    
            void Excute()
            {
                _func(_data);
            }
    
            static void* threadtoutine(void* args)
            {
                Thread<T>* self = (Thread<T>*)args;
                self->Excute();
                return nullptr;
            }
    
            // 启动线程
            bool Start()
            {
                int n = pthread_create(&_tid, nullptr, threadtoutine, this);
                if (n == 0)
                {
                    _stop = false;
                    return true;
                }
                else return false;
            }
    
            // 分离线程
            void Detach()
            {
                if (!_stop)
                {
                    pthread_detach(_tid);
                }
            }
    
            // 等待线程结束
            void Join()
            {
                if (!_stop)
                {
                    pthread_join(_tid, nullptr);
                }
            }
    
            std::string name()
            {
                return _threadname;
            }
    
            // 停止线程
            void Stop()
            {
                _stop = true;
            }
    
            ~Thread(){}
        private:
            pthread_t _tid;
            std::string _threadname;
            T _data;
            func_t<T> _func;
            bool _stop;
        };
    }
    
    #endif
    

    testThread.cc

    #include 
    #include 
    #include "Thread.hpp"
    using namespace ThreadModule;
    
    const int num = 10;
    
    // 线程执行的任务
    void print(int& cnt)
    {
        while (cnt)
        {
            std::cout << "hello I am myself thread, cnt: " << cnt-- << std::endl;
            sleep(1);
        }
    }
    
    int main()
    {
        // 创建多线程
        std::vector<Thread<int>> threads;
        // 创建num个线程,每个线程执行print函数
        for (int i = 0; i < num; ++i)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            threads.emplace_back(print, 10, name);
        }
    
        // 启动线程
        for (auto& thread : threads)
        {
            thread.Start();
        }
    
        // 等待线程结束
        for (auto& thread : threads)
        {
            thread.Join();
            std::cout << "wait thread done, thread name: " << thread.name() << std::endl;
        }
    
        return 0;
    }
    

    结果:
    在这里插入图片描述


    未完待续

  • 相关阅读:
    数据结构上机1
    【Unity】URP渲染管线下代码获取相机的Volume Mask属性
    为Ubuntu网页设置稳定的数据隧道
    西门子6ES72881ST600AA0
    python pytesseract 中文文字批量识别
    使用Java统计gitlab代码行数
    论文阅读《ESSWC2018:Modeling Relational Data with Graph Convolutional Networks》
    Pytest接口自动化测试实战演练
    识别户口本易语言代码
    springboot面试杀手锏-自动配置原理
  • 原文地址:https://blog.csdn.net/m0_69828905/article/details/140388188