马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
学 Linux 线程互斥之前,先把 pthread 封装成 C++ 的 Thread 类,后面写并发代码就清爽了。封装只要抓住三件事:start、stop、join。
一、类的骨架
类内部需要这几样成员:线程名字 _name;线程 ID(等待和停止的关键);运行标记 isrunning(只有运行中的线程才能停、能等);回调函数类型 typedef void (*func_t)(const std::string &name);以及 _result 存返回值。
namespace ThreadMouble
{
typedef void (*func_t)(const std::string &name); // 回调函数类型
class Thread
{
public:
Thread(const std::string &name, func_t func) : _name(name), _func(func) {}
bool Start() {}
void Stop() {}
void Join() {}
~Thread() {}
private:
std::string _name;
pthread_t id;
bool isrunning;
func_t _func;
std::string _result;
};
}
二、线程启动
启动就是调 pthread_create 传参。麻烦在于 pthread_create 要的是 void* (*)(void*) 函数指针,而类内成员函数都隐含 this 参数。做法:把入口函数加 static 变成类静态函数,再靠一个 Excute() 成员去调真正的回调。
void Excute() {
isrunning = true;
_func(_name);
isrunning = false;
}
static void* ThreadRun(void* args) {
Thread* self = static_cast<Thread*>(args);
self->Excute();
return nullptr;
}
bool Start() {
isrunning = true;
int n = ::pthread_create(&id, nullptr, ThreadRun, this);
return n == 0;
}
:: 表示明确使用标准库/系统调用的接口,避免命名污染。
三、线程停止
void Stop() {
if (isrunning) {
isrunning = false;
::pthread_cancel(id);
}
}
四、线程等待
void Join() {
::pthread_join(id, nullptr);
}
五、跑起来看看
封装写好后,主函数 #include "Thread.hpp",给回调里放个 while(true) 循环打日志 ,启动两三个线程看输出交错即可:交错本身就是「共享资源没保护」的现场,正是下一步要上互斥锁的原因。
把 pthread_create/pthread_cancel/pthread_join 这三面墙围起来之后,业务代码只关心「传个名字和回调函数」,互斥锁加在哪里、为什么加,等你看到输出乱序那一刻自然就懂了。
qidao123.com企服评测-应用市场 编辑提示 |