代码仓库地址:https://gitee.com/tgwTTT/linux-learning-dai/tree/master/TestThread3

学习本文建议参考上一篇文章:http://www.tgwttt.xyz/?p=289

现代C++开发中,线程的使用越来越普遍。虽然C++11及以后标准提供了std::thread,但在一些项目中,仍然需要直接使用POSIX线程(pthread)进行更细致的控制。本文将介绍一个基于pthread的线程封装类,也是对POSIX线程库的基本应用巩固

1. 设计目标

我们希望实现一个模板化的线程类,能够:

  • 支持传递任意类型的数据给线程函数
  • 支持线程分离(detach)与等待(join)
  • 支持线程的启动与停止
  • 便于扩展和使用

2. 类定义与成员变量

首先来看类的基本结构。我们使用模板类,支持传递任意类型的数据:

namespace ThreadModlue {
    template
    class Thread {
        using func_t = std::function;
        // ...成员变量定义...
    };
}

主要成员变量包括:

pthread_t tid:线程ID
std::string _name:线程名称
bool _isdetach:是否分离
bool isrunning:是否正在运行
void* res:线程返回值
func_t _func:线程执行的回调函数
T _data:传递给线程的数据

3. 构造函数与命名

每个线程对象都会自动分配一个唯一名称,便于调试和管理:

Thread(func_t func, const T& t)
    : tid(0), _isdetach(false), isrunning(false), _func(func), _data(t) {
    _name = "Thread" + std::to_string(number++);
}

4. 线程启动与执行

线程的启动通过Start()方法实现,内部调用pthread_create

void Start() {
    if (isrunning) return;
    int n = pthread_create(&tid, nullptr, Routine, this);
    if (n > 0) {
        std::cerr << "Thread create failed " << strerror(n) << std::endl;
        return;
    }
    EnableRunning();
}

线程的实际执行逻辑在Routine静态方法中完成:

static void* Routine(void* args) {
    Thread* self = static_cast*>(args);
    if (self->_isdetach)
        self->Detach();
    self->_func(self->_data); // 回调函数
    return nullptr;
}

5. 分离与等待

线程可以选择分离(detach)或等待(join):

  • 分离:线程运行结束后自动释放资源,不能再通过join等待
  • 等待:主线程可以通过join等待子线程结束
void Detach() {
    if (!_isdetach) {
        if (isrunning)
            pthread_detach(tid);
        EnableDetach();
    }
}

void Join() {
    if (_isdetach) {
        std::cerr << "Thread is detached, can't join" << std::endl;
        return;
    }
    int n = pthread_join(tid, &res);
    if (n > 0) {
        std::cerr << "Thread join failed " << strerror(n) << std::endl;
    }
}

6. 停止线程

通过Stop()方法可以尝试取消线程:

void Stop() {
    if (isrunning) {
        int n = pthread_cancel(tid);
        if (n > 0) {
            std::cerr << "Thread cancel failed " << strerror(n) << std::endl;
        } else {
            isrunning = false;
            std::cout << _name << " stopped" << std::endl;
        }
    }
}

今天的更新就到这里,如有错误欢迎评论区指出