- 在多线程编程中,一般会设置一个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 阻塞,则唤醒其中一个
- 线程安全:操作是原子的(不会被其他线程打断)
- 检查信号量值:
4621

被折叠的 条评论
为什么被折叠?



