ZLToolKit 源码分析(二):线程同步原语 semaphore 与 onceToken
高并发框架的基石是同步原语。本文逐行分析 ZLToolKit 自研的 semaphore(信号量)和 onceToken(RAII 守卫),揭示其如何用 C++11 标准库实现高效且安全的线程同步。
1. 为什么不用 std::semaphore?
C++20 才引入std::counting_semaphore,而 ZLToolKit 基于 C++11 开发,必须自研。其实现基于std::condition_variable+std::mutex,语义等价于std::counting_semaphore。
2. semaphore 源码全解
文件:src/Thread/semaphore.h
2.1 完整源码
classsemaphore{public:semaphore(size_t initial=0){_count=initial;}// V 操作:释放信号量voidpost(size_t n=1){std::lock_guard<std::mutex>lock(_mutex);_count+=n;if(n>1){_condition.notify_all();}else{_condition.notify_one();}}// P 操作:获取信号量(阻塞)voidwait(){std::unique_lock<std::mutex>lock(_mutex);while(_count==0){_condition.wait(lock);}--_count;}private:size_t _count;std::mutex _mutex;std::condition_variable _condition;};2.2 逐行精析
post() — 释放信号量
voidpost(size_t n=1){std::lock_guard<std::mutex>lock(_mutex);// RAII 加锁_count+=n;// 增加计数if(n>1){_condition.notify_all();// 释放多个,唤醒所有等待者}else{_condition.notify_one();// 释放一个,只唤醒一个}}关键设计:
n > 1时用notify_all()——因为多个等待者可能都需要被唤醒n == 1时用notify_one()——避免惊群效应(thundering herd)
wait() — 获取信号量
voidwait(){