高性能服务器项目阅读:Thread类的设计

  • 在多线程编程中,一般会设置一个Thread类来管理线程。提供比std::thread 更高一层的管理。首先,该类需要一个执行函数threadFunc(), 这个执行函数应该由用户注册;对于Thread类来说,它并不清楚用户会注册什么类型的函数
class Thread {
using std::function<void()> ThreadFunc;
public:
Thread(ThreadFunc f) {
func_ = f;
}
void start() {
std::thread t(func_);
t.detach();
}
private:
ThreadFunc func_;
};

外部的用法就是:
Thread thread_(add);
thread_.start();

一般来说,多线程服务器都要有一个日志系统方便排查问题,而日志需要记录运行中线程的tid,我们可以将其放入Thread类中进行管理:

class Thread {
using std::function<void()> ThreadFunc;
public:
Thread(ThreadFunc f) {
func_ = f;
}
void start() {
std::thread t(funcWrapper);
std::cout<<tid<<std::endl;
t.detach();
}
void funcWrapper() {
tid = CurrentThread::tid();
func();
}
private:
ThreadFunc func_;
pid_t tid;
};

但这样写有一个问题,就是当主线程创建子线程后,有可能在子线程返回其tid之前就访问tid(std::cout<<tid<<std::endl)了,这个就会导致结果不正确。这是典型的线程同步问题,可以采用信号量解决:

class Thread {
using std::function<void()> ThreadFunc;
public:
Thread(ThreadFunc f) {
func_ = f;
sem_init(&sem_t, false, 0); 

}
void start() {
std::thread t(funcWrapper);
sem_wait(&sem_t);
std::cout<<tid<<std::endl;
t.detach();
}
void funcWrapper() {
tid = CurrentThread::tid();
sem_post(&sem_t);
func();
}
private:
ThreadFunc func_;
pid_t tid;
sem_t sem;
};

其中:

  • sem_wait​​(P操作):尝试获取信号量(若计数器 ≤ 0,则阻塞)
    • 检查信号量值
      • 如果 sem > 0​​:将 sem 减 1,并立即返回
      • 如果 sem == 0​​:阻塞当前线程,直到其他线程调用 sem_post。
    • 线程安全​​:操作是原子的(不会被其他线程打断)
  • ​​sem_post​​(V操作):释放信号量(计数器 +1,唤醒等待的线程)
    • 检查信号量值:
      • 将信号量值 ​​+1​​
      • 如果之前有线程因 sem_wait 阻塞,则唤醒其中一个
    • 线程安全​​:操作是原子的(不会被其他线程打断)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值