Linux-线程封装

**摘要:**本文基于 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

或者Gitee:fthread · 谭旦0000/test_for_csdn - 码云 - 开源中国

相关推荐
god_cvz1 小时前
实践:Linux环境构建CTB工具(cesium-terrain-builder)
linux·gis·ctb
n112121 小时前
Docker 容器时区错 8 小时:3 个坑
运维·docker·容器·故障排查·服务器运维·容器时区
Android系统攻城狮1 小时前
Linux FFmpeg深度解析之av_dump_format调用流程与实战(十一)
linux·运维·服务器·ffmpeg·1024程序员节·音视频进阶
Android系统攻城狮1 小时前
Linux FFmpeg深度解析之avcodec_find_decoder调用流程与实战(十二)
linux·运维·服务器·ffmpeg·1024程序员节·音视频进阶
小白的码BUG之路2 小时前
K8s -- 启动一主二从节点
linux·运维·服务器
Escalating_xu2 小时前
【Linux 网络编程】IP 分片与重组:3000 字节的数据报,怎样拆开又拼回来?
linux·网络·tcp/ip
小相会自律2 小时前
全平台远程控制软件推荐2026:Win/Mac/Linux/手机/鸿蒙互通哪款好
linux·macos·智能手机·todesk·teamviewer·向日葵
yyzc111112 小时前
合规稳定资金结算收款系统助力门店发展
大数据·运维·人工智能
AI_Lab012 小时前
服务器管理工具要在服务器上装 Agent,安全吗?
服务器·安全·github