当前位置: 首页 > web >正文

【Linux】线程封装

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

一、为什么需要封装线程库?

pthread的痛点:

封装带来的好处:

二、线程封装核心代码解析

1. 头文件定义(Thread.hpp)

三、关键技术点详解

1. std::function的魅力

2. 静态成员函数的巧妙使用

3. 获取真实的线程ID

四、使用示例和测试代码

测试代码(main.cpp)


一、为什么需要封装线程库?

在Linux C++开发中,我们经常需要使用多线程。原生的pthread接口虽然强大,但存在一些问题:

pthread的痛点:

  • 🔧 C风格接口:函数指针和void*参数不够类型安全

  • 📝 冗长的代码:需要手动管理线程创建、连接、销毁

  • 🚫 易出错:容易忘记检查返回值,导致难以调试的问题

  • 🔄 缺乏RAII:资源管理需要手动处理

封装带来的好处:

  • 🎯 类型安全:使用std::function代替函数指针

  • 🚀 简洁易用:几行代码完成线程管理

  • 🛡️ 异常安全:利用RAII自动管理资源

  • 📦 可扩展性:方便添加新功能(如线程池)

二、线程封装核心代码解析

1. 头文件定义(Thread.hpp)

 

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <functional>
#include <sys/syscall.h>// 获取轻量级进程ID(线程ID)
#define get_lwp_id() syscall(SYS_gettid)// 定义函数类型别名
using func_t = std::function<void()>;class Thread
{
public:// 构造函数:接收线程函数和线程名Thread(func_t func, const std::string &name): _name(name), _func(func), _isrunning(false){}// 静态成员函数:线程启动例程static void *start_routine(void *args){Thread *self = static_cast<Thread *>(args);self->_isrunning = true;self->_lwpid = get_lwp_id();  // 获取实际线程IDself->_func();                // 执行用户函数pthread_exit((void *)0);      // 线程退出}// 启动线程void Start(){int n = pthread_create(&_tid, nullptr, start_routine, this);if (n == 0){std::cout << "线程" << _name << "创建成功" << std::endl;}}// 等待线程结束void Join(){if (!_isrunning) return;int n = pthread_join(_tid, nullptr);if (n == 0){std::cout << "线程" << _name << "回收成功" << std::endl;}}~Thread() {}private:bool _isrunning;        // 线程运行状态pthread_t _tid;         // 线程IDpid_t _lwpid;           // 轻量级进程IDstd::string _name;      // 线程名称func_t _func;           // 线程执行函数
};

三、关键技术点详解

1. std::function的魅力

传统pthread的问题:

 // C风格:需要静态函数和void*参数
void* thread_func(void* arg) {// 需要类型转换int* data = (int*)arg;// ...
}

我们的解决方案:

 

// C++11风格:类型安全的函数对象
using func_t = std::function<void()>;// 可以接收任何可调用对象:
// 1. 普通函数
// 2. Lambda表达式  
// 3. 函数对象
// 4. std::bind表达式

2. 静态成员函数的巧妙使用

为什么需要静态函数?
pthread_create要求C风格的函数指针,但普通成员函数有隐式的this参数。

解决方案:

 

static void *start_routine(void *args) {Thread *self = static_cast<Thread *>(args);  // 转换回对象指针self->_func();  // 调用真正的线程函数
}

3. 获取真实的线程ID

 

#define get_lwp_id() syscall(SYS_gettid)// 为什么需要这个?
// - pthread_t是进程内标识,在不同进程中可能重复
// - 通过系统调用获取的LWP ID是系统范围内唯一的
// - 便于调试和系统监控

四、使用示例和测试代码

测试代码(main.cpp)

 

#include "Thread.hpp"
#include <iostream>
#include <vector>// 测试函数
void Test()
{int cnt = 3;while (cnt--){std::cout << "线程" << get_lwp_id() << "正在运行..." << std::endl;sleep(1);}
}// Lambda表达式测试
auto lambda_test = []() {std::cout << "Lambda线程运行中" << std::endl;sleep(2);
};int main()
{std::cout << "=== 单线程测试 ===" << std::endl;Thread t1(Test, "single-thread");t1.Start();t1.Join();std::cout << "\n=== 多线程测试 ===" << std::endl;std::vector<Thread> threads;// 创建3个线程for (int i = 0; i < 3; i++){std::string name = "thread-";name += std::to_string(i + 1);threads.emplace_back(Test, name);}// 启动所有线程for (auto &thread : threads){thread.Start();}// 等待所有线程结束for (auto &thread : threads){thread.Join();}std::cout << "\n=== Lambda测试 ===" << std::endl;Thread t2(lambda_test, "lambda-thread");t2.Start();t2.Join();return 0;
}

http://www.xdnf.cn/news/19983.html

相关文章:

  • 【FastDDS】Layer DDS之Domain ( 04-DomainParticipantFactory)
  • 采用基于模型的方法实现车辆SOA威胁分析自动化
  • wpf 自定义密码文本框,并且可以双向绑定
  • 吱吱企业通讯软件以安全为核心,构建高效沟通与协作一体化平台
  • 什么是Agent?小白如何学习使用Agent?一篇文档带你详细了解神秘的Agent
  • 容器tomcat镜像制作
  • 算法题2:动态规划
  • Python委托迭代完全指南:从基础到高级设计模式实践
  • Vision Pro图像处理工具全解析
  • Hadoop HDFS-SecondaryNameNode(2nn)详细介绍
  • PPI网络与TF-miRNA调控网络的实现方法(基于《列腺癌研究.pdf》)
  • 跟做springboot尚品甄选项目
  • 理解用户需求
  • 第6章:垃圾回收分析与调优
  • Java内存模型解析:并发编程的基石
  • DARPA OFFSET公开资料探究
  • GEO优化专家孟庆涛:优质内容是GEO优化的核心
  • 后端一次性返回十万条数据时,前端需要采用多种性能优化策略来避免页面卡顿
  • 日志打印--idf的esp32
  • Agent开发基础---提示词编写
  • 【数据分享】土地利用矢量shp数据分享-北京
  • AI Agent重构SOC:下一代智能安全运营平台的能力跃迁
  • 产线自动化效率上不去?打破设备和平台的“数据孤岛”是关键!
  • LeetCode 面试题 16.06.最小差
  • JavaScript原型与原型链:对象的家族传承系统
  • Springboot3+SpringSecurity6Oauth2+vue3前后端分离认证授权-资源服务
  • 单片机键盘接口程序设计(汇编语言)
  • 血缘元数据采集开放标准:OpenLineage Guides 在 Airflow 中使用 OpenLineage Proxy
  • 快速在RK3588上部署运行DeepSeek-R1-Distill-Qwen-1.5B模型并进行板端推理调用流程记录
  • 重生之IOday4————多进程通信