在任务同步当中二值信号量sem和事件/条件变量evt的区别
2026/8/14 23:34:42 网站建设 项目流程

内部实现

信号量sem

POSIX sem_t

信号量的用处

  1. 需要计数任务时,因为信号量可以统计数量
  2. 当中任务通知用(实际上FreeRTOS的任务通知就是轻量化的二进制信号量(可以替代掉二进制信号量))
  3. 当互斥锁用(但是不推荐,因为无法解决优先级反转的问题)

事件evt

pthread_cond_t+pthread_mutex_t主要依靠条件变量实现

使用区别

  1. 信号量需要计数
  2. 事件只有两种状态

不需要信号量计数的情况下

区别1:先Post(释放)后Pend(请求),结果不同

信号量(sem_post):Post 会累加计数,即使没人等也不丢
计数0→1 → 计数1→0,立即返回成功 ✓
OS_SemPost 底层是 sem_post,它会把信号量的值从0加到1,这个值会保留下来,后续 sem_wait 来了直接拿走,不会阻塞。

事件(pthread_cond_signal):Post 时没人在等,signal 就丢了
无人等待,signal丢失 → 永远阻塞 ✗
OS_EvtPost 底层是 pthread_cond_signal,它只是唤醒当前正在 pthread_cond_wait 上的线程。如果那一刻没有线程在 wait,这个 signal 就消失了,什么也没留下。

区别2:事件存在"虚假唤醒"

pthread_cond_wait 在 Linux 上可能没有人 Post 也会自己醒来(操作系统实现层面的已知问题),所以条件变量的正确用法必须配合 while 循环和条件变量检查:

条件变量(pthread_cond)的不可替代之处

在上面的描述过程当中,好像感觉pthread_cond挺没有用的,实则不然。

  1. 广播唤醒
    信号量的 sem_post 每次只能让一个 sem_wait 返回。如果想唤醒5个线程,必须 sem_post 5次。
    条件变量的 pthread_cond_broadcast 可以一次唤醒所有正在等待的线程。

  2. 等的是条件,不是信号
    信号量只能告诉你"有人 Post 了",但不知道具体是什么条件满足了。

条件变量的真正用法是:等待某个条件为真,而不是等待一个信号。

信号量思维:等一个通知 → 通知来了就往下走
条件变量思维:等一个条件 → 条件满足往下走,不满足继续等

  1. 信号丢失的优势
    条件变量:3次上报 → 只保留最新1次通知 → 处理线程醒来1次,只处理最新数据

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询