信号量存在等待线程时,主线程为何能自我post并优先执行?
信号量sem_post后主线程sem_wait优先执行的原因
为理解信号量(semaphore)的语义,我编写了如下代码:
#include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> sem_t sem; void *helper(void *arg) { sem_wait(&sem); printf("helper woke up\n"); } int main() { sem_init(&sem, 0, 0); pthread_t tid; pthread_create(&tid, NULL, helper, NULL); sleep(1); sem_post(&sem); sem_wait(&sem); printf("main woke up\n"); exit(0); }
运行后输出为:
main woke up
而非预期的:
helper woke up
根据手册描述:
If the semaphore's value consequently becomes greater than zero, then another process or thread blocked in a sem_wait(3) call will be woken up and proceed to lock the semaphore.
请问:当信号量已有等待线程时,为何主线程调用sem_post后自身的sem_wait能优先执行,而非唤醒等待的helper线程?
这是因为POSIX信号量并没有规定等待线程的唤醒顺序,也没有保证调用sem_post后必须优先唤醒已阻塞的线程。
你的代码里,主线程调用sem_post后,信号量的值从0变为1。此时存在两种执行路径:
- 主线程在调用
sem_post后仍处于运行状态,立刻执行后续的sem_wait,直接将信号量从1减回0,主线程继续执行; - 调度器切换到helper线程,让它的
sem_wait获取信号量,输出"helper woke up"。
实际运行中出现第一种情况,是因为主线程调用sem_post后未被调度器打断,它的sem_wait在信号量值为1时直接成功,无需阻塞,自然就优先执行了。
手册描述仅说明"会唤醒一个阻塞的线程",但并没有规定这个唤醒动作必须在当前线程的后续代码执行前完成。线程的执行顺序由调度器的调度策略决定,信号量本身不强制唤醒顺序。
如果想确保helper线程先执行,可以在sem_post后加入pthread_yield()主动让出CPU,或者使用互斥锁+条件变量这类同步原语来明确控制执行顺序。
内容的提问来源于stack exchange,提问作者Josh Levi
相关产品推荐
相关产品推荐

