
摘要本文基于 pthread 从零封装一个 C 线程类 Thread逐步解决类内成员函数作为线程入口导致的编译报错问题通过 static 入口函数配合 this 指针传参完成回调绑定同时引入 _isrunning 标志位控制线程启动状态与 Join 的合法性并借助 syscall(SYS_gettid) 获取线程底层 LWP最终给出可直接复用的完整线程封装代码。我们需要写一个线程封装实现我们自己的一个线程类才能更加深入了解线程#ifndef __THREAD_HPP__ #define __THREAD_HPP__ #includeiostream #includevector #includepthread.h #includestring #includefunctional using func_t std::functionvoid(); //默认名字 const std::string threadnamedefault None-Name; //线程类 class Thread { public: Thread(func_t func,const std::string name threadnamedefault) :_name(name) ,_func(func) {} void* start_routine(void* args) { } void Start() { int n pthread_create(_tid,nullptr,start_routine,nullptr); } void Join() { int n pthread_join(_tid,nullptr); if(n 0) { //等待线程成功 std::cout 等待线程成功 std::endl; } } ~Thread(){} private: pthread_t _tid;//线程ID pthread_t _lwpid;//底层的LWP std::string _name;//线程名字 func_t _func;//线程执行的方法 }; #endif但是这样写会出现波浪号这是因为我们的start_routine是类内函数需要使用this指针可以这样写void* start_routine(Thread* this,void* args)我们也可以这样写static void* start_routine(void* args)因为我们的这个类并没有被实例化所以这个会报错我们也可以把它放到类外面去不过那样比较麻烦因此此时我们就可以传递参数了int n pthread_create(_tid,nullptr,start_routine,this);此时的start_routine就可以改为我们还需要一个标志位来代表线程是否启动bool _isrunning;//线程是否被启动只有当start_routine函数即该类执行的方法开始了才会启动此外如果线程没有启动那么就不能Join//检测线程结束并且回收 void Join() { if(!_isrunning) return; int n pthread_join(_tid,nullptr); if(n 0) { //等待线程成功 std::cout 等待线程成功 std::endl; } }我们现在可以获取线程的LWP需要添加#includeunistd.h #includesys/syscall.h #define get_lwp_id() syscall(SYS_gettid)其实现在这结构已经能够做到基本的操作了主要代码#ifndef __THREAD_HPP__ #define __THREAD_HPP__ #includeiostream #includevector #includepthread.h #includeunistd.h #includestring #includefunctional #includesys/syscall.h #define get_lwp_id() syscall(SYS_gettid) using func_t std::functionvoid(); //默认名字 const std::string threadnamedefault None-Name; //线程类 class Thread { public: Thread(func_t func,const std::string name threadnamedefault) :_name(name) ,_func(func) ,_isrunning(false) { //创建线程成功 std::cout 创建线程成功 std::endl; } static void* start_routine(void* args) { Thread* self static_castThread*(args);//用于接受外部传入的函数参数 //将线程启动 self-_isrunning true; //获取线程ID self-_lwpid get_lwp_id(); //回调我们自己的方法 self-_func(); //返回 pthread_exit((void*)0); } void Start() { int n pthread_create(_tid,nullptr,start_routine,this); //启动线程成功 if(n 0) std::cout 启动线程成功 std::endl; } //检测线程结束并且回收 void Join() { if(!_isrunning) return; int n pthread_join(_tid,nullptr); if(n 0) { //等待线程成功 std::cout 等待线程成功 std::endl; } } ~Thread(){} private: bool _isrunning;//线程是否被启动 pthread_t _tid;//线程ID pthread_t _lwpid;//底层的LWP std::string _name;//线程名字 func_t _func;//线程执行的方法 }; #endif或者Gitee:fthread · 谭旦0000/test_for_csdn - 码云 - 开源中国