线程封装指的是将线程的创建、管理和执行逻辑封装成一个独立的模块或对象,以便简化程序设计并提高代码的可重用性和可维护性。其意义在于:简化代码:避免直接操作线程,减少复杂性。提高可读性:通过封装,代码结构更加清晰。增强灵活性:方便修改和扩展线程的行为。提升并发管理:能够更好地控制线程生命周期和资源管理。总体来说,线程封装让多线程编程更加高效和安全。
template <typename T>
class Thread {
// ...
};
private:
pthread_t _tid; // 底层线程ID
std::string _name; // 线程名称(调试用)
bool _isdetach; // 分离状态标志
bool _isrunning; // 运行状态标志
void* _res; // pthread_join返回值存储
using func_t = std::function<void(T)>;
func_t _func; // 用户任务存储
T _data; // 任务参数存储
static void *Routine(void *args) // 类内的成员函数默认含有this指针
{
Thread<T> *self = static_cast<Thread<T> *>(args);
self->EnableRunning();
if (self->_isdetach)
self->Detach();
pthread_setname_np(self->_tid, self->_name.c_str());//获取线程名字
self->_func(self->_data);//执行回调函数
return nullptr;
}
void EnableRunning()
{
_isrunning = true;
}
bool Start()
{
if (_isrunning)//判断线程是否已处于运行状态,如果已是运行状态,直接返回即可,否则创建新的线程
return false;
int n = pthread_create(&_tid, nullptr, Routine, this);//创建新线程
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
return false;
}
else
{
std::cout << _name << "create success" << std::endl;
return true;
}
}
如果该线程不是分离的且在运行,才可以进行线程分离。
void Detach() {
if (!_isdetach && _isrunning) {
pthread_detach(_tid);
EnableDetach();
}
}
如果线程是正在运行的运行的状态,才进行终止。
bool Stop()
{
// 如果线程正在运行,执行停止操作
if (_isrunning)
{
// 尝试取消线程的执行
int n = pthread_cancel(_tid);
// 如果线程取消失败,打印错误信息并返回 false
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
return false;
}
else
{
// 成功取消线程,更新状态并输出停止信息
_isrunning = false;
std::cout << _name << "Stop" << std::endl;
return true;
}
}
// 如果线程没有运行,返回 false
return false;
}
如果线程已经是分离的,就不需要等待了,否则就join。
void Join()
{
// 如果线程已经被分离(即线程已独立),则无法再执行 Join 操作
if (_isdetach)
{
std::cout << "你的线程已经是Join了,不能在Join了" << std::endl; // 输出错误信息
return; // 直接返回,不执行后续操作
}
// 调用 pthread_join 等待线程完成
int n = pthread_join(_tid, &_res);
// 如果调用 pthread_join 出现错误,打印错误信息
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
}
// 如果线程成功完成,输出 Join 成功信息
std::cout << "Join success" << std::endl;
}
_name = “Thread-” + std::to_string(number++); pthread_setname_np(_tid, _name.c_str());
// 启动线程并标记为正在运行
void EnableRunning() {
_isrunning = true; // 将线程的运行状态设置为 true,表示线程正在运行
}
这个函数的作用是标记线程已启动或者正在运行,通常在创建线程后被调用来更新线程的状态。
线程栈是操作系统为每个线程独立分配的内存区域,用于管理函数调用、局部变量和上下文切换。
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 16 * 1024 * 1024); // 设置为16MB
pthread_create(&tid, &attr, Routine, nullptr);
void deep_recursion(int depth) {
char buffer[1024]; // 每个栈帧占用1KB
memset(buffer, 0, sizeof(buffer));
deep_recursion(depth + 1);
}
int main() {
deep_recursion(0); // 默认栈大小下约1024层递归溢出
return 0;
}
输出:
Segmentation fault (core dumped) 解决方案:
维度 | 说明 |
---|---|
隔离性 | 每个线程独立栈,避免函数调用冲突 |
自动管理 | 无需手动分配/释放,降低内存泄漏风险 |
性能优化 | 高速访问(L1缓存友好),但需平衡栈深度与内存占用 |
调试支持 | 通过调用栈快速定位问题,但需注意优化对调试信息的影响 |
理解线程栈机制是进行高性能并发编程的基础,合理设计函数调用链和内存使用模式,可显著提升程序稳定性和执行效率。
本文详述了C++线程封装实现与线程栈管理机制。线程封装通过模板类实现类型安全的线程创建、任务绑定及生命周期管理,核心设计包括静态入口函数传递this指针解决对象上下文问题,以及分离/终止/等待等控制方法。线程栈部分解析了其独立内存布局、栈帧结构及动态增长特性,探讨了栈溢出防护、并发安全优化策略,并结合示例说明了大栈帧递归的风险与解决方案,为高性能多线程编程提供实践指导。
//1. Thread.hpp
#ifndef _THREAD_H_
#define _THREAD_H_
#include <iostream>
#include <string>
#include <pthread.h>
#include <cstdio>
#include <cstring>
#include <functional>
namespace ThreadModlue
{
static uint32_t number = 1;
template <typename T>
class Thread
{
using func_t = std::function<void(T)>;
private:
void EnableDetach()
{
std::cout << "线程被分离了" << std::endl;
_isdetach = true;
}
public:
Thread(func_t func, T data)
: _tid(0),
_isdetach(false),
_isrunning(false),
_res(nullptr),
_func(func),
_data(data)
{
_name = "THread-" + std::to_string(number++);
}
void Detach()
{
if (_isdetach)
return;
if (_isrunning)
pthread_detach(_tid);
EnableDetach();
}
static void *Routine(void *args) // 类内的成员函数默认含有this指针
{
Thread<T> *self = static_cast<Thread<T> *>(args);
self->EnableRunning();
if (self->_isdetach)
self->Detach();
pthread_setname_np(self->_tid, self->_name.c_str());
self->_func(self->_data);
return nullptr;
}
void EnableRunning()
{
_isrunning = true;
}
bool Start()
{
if (_isrunning)//判断线程是否已处于运行状态,如果已是运行状态,直接返回即可,否则创建新的线程
return false;
int n = pthread_create(&_tid, nullptr, Routine, this);//创建新线程
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
return false;
}
else
{
std::cout << _name << "create success" << std::endl;
return true;
}
}
bool Stop()
{
if (_isrunning)
{
int n = pthread_cancel(_tid);
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
return false;
}
else
{
_isrunning = false;
std::cout << _name << "Stop" << std::endl;
return true;
}
_isrunning = false;
}
return false;
}
void Join()
{
if (_isdetach)
{
std::cout << "你的线程已经是Join了,不能在Join了" << std::endl;
return;
}
int n = pthread_join(_tid, &_res);
if (n != 0)
{
std::cerr << "create thread error: " << strerror(n) << std::endl;
}
std::cout << "Join success" << std::endl;
}
~Thread()
{
}
private:
pthread_t _tid;
std::string _name;
bool _isdetach;
bool _isrunning;
void *_res;
func_t _func;
T _data;
};
}
#endif
//2. Main.cc
#include "Thread.hpp"
#include <unistd.h>
using namespace ThreadModlue;
void Count(int cnt)
{
while (cnt--)
{
char name[128];
pthread_getname_np(pthread_self(),name,sizeof(name));
std::cout << "我是一个新线程: " << std::endl;
sleep(1);
}
}
int main()
{
int cnt = 10;
Thread<int> t(Count, cnt);
// Thread t([](){
// while(true)
// {
// std::cout << "我是一个新线程" << std::endl;
// sleep(1);
// }
// });
// t.Start();
// sleep(5);
// t.Stop();
// sleep(5);
// t.Join();
return 0;
}
//3. Makefile
test:Main.cc
g++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:
rm -f test