C++线程能否自通知条件变量?计数信号量是否更适用?
问题解答
线程能否通知自身唤醒?
线程可以调用notify_one()通知自身,但你的现有代码存在关键问题:接收线程调用sender()时,手里还持有std::unique_lock(仍处于while循环的锁作用域内),此时触发的receiver_cv.notify_one()会直接丢失——因为条件变量的通知是“一次性”的,没有被正在等待的线程接收就会失效,无法累积唤醒次数,这正好和你需要“记录唤醒次数”的需求冲突。
C++20计数信号量是不是更好的方案?
是的,std::counting_semaphore完全匹配你的场景需求:
- 它本身具备计数存储能力,每调用一次
release()(对应你的通知动作)就会将计数器加1,调用acquire()(对应等待动作)则将计数器减1;当计数器为0时,acquire()会阻塞等待。 - 无论主线程还是接收线程调用
release(),信号量都会把唤醒次数保存下来,不会出现通知丢失的情况。 - 接收线程每次循环调用
acquire()时,会按计数器记录的次数依次唤醒处理,完美实现“按对应次数唤醒”的要求。
改造后的伪代码示例
#include <semaphore> // 初始化信号量,初始计数为0,对应初始无待处理任务 std::counting_semaphore<1024> recv_sem(0); void sender() { auto request = create_new_packet(); socket.sendBytes(request); // 每发送一次数据包,增加一个唤醒计数 recv_sem.release(); } void receiver() { while(true) { // 等待信号量,计数器减1;若计数器为0则阻塞 recv_sem.acquire(); socket.receiveBytes(); // ... 处理逻辑 if(需要发送新数据包) { sender(); } } }
额外说明
- 信号量的模板参数是最大计数,可根据实际业务场景调整(示例中1024足以应对多数常规情况)。
- 无需再使用
std::mutex和std::condition_variable,信号量已内置同步机制,代码更简洁。 - 接收线程调用
sender()时,release()会直接累加计数器,下一轮循环的acquire()能立刻获取到该计数,彻底解决自通知时的丢失问题。
内容的提问来源于stack exchange,提问作者neuron mac
相关产品推荐
相关产品推荐

