**摘要:**本文基于 pthread 从零封装一个 C++ 线程类 Thread,逐步解决类内成员函数作为线程入口导致的编译报错问题,通过 static 入口函数配合 this 指针传参完成回调绑定;同时引入 _isrunning 标志位控制线程启动状态与 Join 的合法性,并借助 syscall(SYS_gettid) 获取线程底层 LWP,最终给出可直接复用的完整线程封装代码。
我们需要写一个线程封装,实现我们自己的一个线程类才能更加深入了解线程:
cpp
#ifndef __THREAD_HPP__
#define __THREAD_HPP__
#include<iostream>
#include<vector>
#include<pthread.h>
#include<string>
#include<functional>
using func_t = std::function<void()>;
//默认名字
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指针!
可以这样写:
cpp
void* start_routine(Thread* this,void* args)
我们也可以这样写:
cpp
static void* start_routine(void* args)
因为我们的这个类并没有被实例化,所以这个会报错,我们也可以把它放到类外面去,不过那样比较麻烦!
因此,此时我们就可以传递参数了:
cpp
int n = pthread_create(&_tid,nullptr,start_routine,this);
此时的start_routine就可以改为:
我们还需要一个标志位来代表线程是否启动:
cpp
bool _isrunning;//线程是否被启动
只有当start_routine函数即该类执行的方法开始了才会启动:

此外,如果线程没有启动,那么就不能Join:
cpp
//检测线程结束并且回收
void Join()
{
if(!_isrunning)
return;
int n = pthread_join(_tid,nullptr);
if(n == 0)
{
//等待线程成功
std::cout << "等待线程成功" << std::endl;
}
}
我们现在可以获取线程的LWP,需要添加:
cpp
#include<unistd.h>
#include<sys/syscall.h>
#define get_lwp_id() syscall(SYS_gettid)
其实现在这结构已经能够做到基本的操作了,主要代码:
cpp
#ifndef __THREAD_HPP__
#define __THREAD_HPP__
#include<iostream>
#include<vector>
#include<pthread.h>
#include<unistd.h>
#include<string>
#include<functional>
#include<sys/syscall.h>
#define get_lwp_id() syscall(SYS_gettid)
using func_t = std::function<void()>;
//默认名字
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_cast<Thread*>(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